diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 76c7f1639f9..fc639352f37 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -664,6 +664,7 @@ config/form_profile_mappings/0873.yml @department-of-veterans-affairs/vfs-virtua
config/form_profile_mappings/1010ez.yml @department-of-veterans-affairs/vfs-10-10 @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
config/form_profile_mappings/10-10EZR.yml @department-of-veterans-affairs/vfs-10-10 @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
config/form_profile_mappings/10182.yml @department-of-veterans-affairs/Benefits-Team-1 @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
+config/form_profile_mappings/10-7959F-1.yml @department-of-veterans-affairs/champva-engineering @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
config/form_profile_mappings/20-0995.yml @department-of-veterans-affairs/Benefits-Team-1 @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
config/form_profile_mappings/20-0996.yml @department-of-veterans-affairs/Benefits-Team-1 @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
config/form_profile_mappings/21-526EZ.yml @department-of-veterans-affairs/Disability-Experience @department-of-veterans-affairs/va-api-engineers @department-of-veterans-affairs/backend-review-group
diff --git a/Dockerfile b/Dockerfile
index 11836e43a76..96c748bbb5a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,4 @@
-ARG RELEASE=bullseye
-FROM ruby:3.2.3-slim-${RELEASE} as rubyimg
+FROM ruby:3.2.3-slim-bookworm as rubyimg
# XXX: using stretch here for pdftk dep, which is not availible after
# stretch (or in alpine) and is switched automatically to pdftk-java in buster
@@ -18,21 +17,15 @@ RUN find modules -type f ! \( -name Gemfile -o -name "*.gemspec" -o -path "*/lib
# shared build/settings for all child images, reuse these layers yo
###
FROM rubyimg AS base
-ARG RELEASE
-ENV RELEASE="$RELEASE"
ARG userid=993
SHELL ["/bin/bash", "-c"]
RUN groupadd -g $userid -r vets-api && \
useradd -u $userid -r -m -d /srv/vets-api -g vets-api vets-api
-RUN echo "APT::Default-Release \"${RELEASE}\";" >> /etc/apt/apt.conf.d/99defaultrelease
-RUN mv /etc/apt/sources.list /etc/apt/sources.list.d/stable.list
-RUN echo "deb http://ftp.debian.org/debian testing main contrib non-free" >> /etc/apt/sources.list.d/testing.list
-RUN echo "deb http://deb.debian.org/debian unstable main" >> /etc/apt/sources.list.d/unstable.list
-RUN apt-get update
-RUN DEBIAN_FRONTEND=noninteractive apt-get install -y -t "${RELEASE}" \
- dumb-init imagemagick pdftk poppler-utils curl libpq5 vim libboost-all-dev \
- clamav clamdscan clamav-daemon
+RUN apt-get update --fix-missing
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates-java && \
+ DEBIAN_FRONTEND=noninteractive apt-get install -y dumb-init imagemagick pdftk poppler-utils curl \
+ libpq5 vim libboost-all-dev clamav clamdscan clamav-daemon
# The pki work below is for parity with the non-docker BRD deploys to mount certs into
# the container, we need to get rid of it and refactor the configuration bits into
diff --git a/Gemfile b/Gemfile
index 3d0de296b6e..94355520763 100644
--- a/Gemfile
+++ b/Gemfile
@@ -58,7 +58,7 @@ gem 'carrierwave-aws'
gem 'clam_scan'
gem 'combine_pdf'
gem 'config'
-gem 'connect_vbms', git: 'https://github.com/department-of-veterans-affairs/connect_vbms.git', branch: 'master', require: 'vbms'
+gem 'connect_vbms', git: 'https://github.com/adhocteam/connect_vbms', tag: 'v2.0.0.rc', require: 'vbms'
gem 'date_validator'
gem 'ddtrace'
gem 'dogstatsd-ruby', '5.6.1'
diff --git a/Gemfile.lock b/Gemfile.lock
index 6971cc5e88e..d347bccd1bc 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,3 +1,17 @@
+GIT
+ remote: https://github.com/adhocteam/connect_vbms
+ revision: 6e5dc751afaf0da9c7cbc10c94b909f114f3a156
+ tag: v2.0.0.rc
+ specs:
+ connect_vbms (2.0.0.rc)
+ httpclient (~> 2.8.0)
+ httpi (~> 2.4)
+ mail
+ nokogiri (>= 1.8.4)
+ nori
+ xmldsig (~> 0.3.1)
+ xmlenc
+
GIT
remote: https://github.com/department-of-veterans-affairs/apivore
revision: f8ccd476f6c5301f5ebe4e2dd5b30ff0e567ffc1
@@ -30,20 +44,6 @@ GIT
nokogiri (>= 1.13.6)
savon (= 2.12)
-GIT
- remote: https://github.com/department-of-veterans-affairs/connect_vbms.git
- revision: 1834cf61310001c82e2e96d665518407c3bce947
- branch: master
- specs:
- connect_vbms (1.4.0)
- httpclient (~> 2.8.0)
- httpi (~> 2.4)
- mail
- nokogiri (>= 1.8.4)
- nori
- xmldsig (~> 0.3.1)
- xmlenc
-
GIT
remote: https://github.com/department-of-veterans-affairs/fhir_client.git
revision: 52e0197dcb1f940a1f0b28bfa983699f0c199696
@@ -317,7 +317,7 @@ GEM
content_disposition (1.0.0)
cork (0.3.0)
colored2 (~> 3.1)
- coverband (6.1.0)
+ coverband (6.1.1)
redis (>= 3.0)
crack (1.0.0)
bigdecimal
@@ -663,7 +663,8 @@ GEM
nokogiri (1.16.4)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
- nori (2.6.0)
+ nori (2.7.0)
+ bigdecimal
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
@@ -692,7 +693,7 @@ GEM
os (1.1.4)
ox (2.14.18)
parallel (1.24.0)
- parallel_tests (4.6.1)
+ parallel_tests (4.7.0)
parallel
parser (3.3.0.5)
ast (~> 2.4.1)
@@ -890,7 +891,7 @@ GEM
rswag-ui (2.13.0)
actionpack (>= 3.1, < 7.2)
railties (>= 3.1, < 7.2)
- rubocop (1.63.2)
+ rubocop (1.63.3)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
@@ -997,7 +998,7 @@ GEM
stringio (3.1.0)
strong_migrations (1.8.0)
activerecord (>= 5.2)
- super_diff (0.11.0)
+ super_diff (0.12.0)
attr_extras (>= 6.2.4)
diff-lcs
patience_diff
diff --git a/app/controllers/v0/profile/direct_deposits_controller.rb b/app/controllers/v0/profile/direct_deposits_controller.rb
index 942a666f594..ff08ee72400 100644
--- a/app/controllers/v0/profile/direct_deposits_controller.rb
+++ b/app/controllers/v0/profile/direct_deposits_controller.rb
@@ -11,8 +11,7 @@ module Profile
class DirectDepositsController < ApplicationController
service_tag 'direct-deposit'
before_action { authorize :lighthouse, :direct_deposit_access? }
- before_action :payment_account, only: :update
- before_action :control_information, only: :update
+
after_action :log_sso_info, only: :update
rescue_from(*Lighthouse::ServiceException::ERROR_MAP.values) do |exception|
@@ -28,12 +27,19 @@ class DirectDepositsController < ApplicationController
def show
response = client.get_payment_info
+ set_control_information(response.body[:control_information])
+ log_control_info(@control_information, 'Show')
+
render status: response.status,
json: response.body,
serializer: DisabilityCompensationsSerializer
end
def update
+ set_control_information(control_info_params)
+ set_payment_account(payment_account_params)
+
+ log_control_info(@control_information, 'Update')
response = client.update_payment_info(@payment_account)
send_confirmation_email
@@ -44,6 +50,15 @@ def update
private
+ def log_control_info(control_info, action)
+ ::Rails.logger.info("Direct Deposit Control Info: #{action}",
+ { benefit_type: control_info.benefit_type,
+ updatable: control_info.account_updatable?,
+ valid: control_info.valid?,
+ restrictions: control_info.restrictions.join(', '),
+ errors: control_info.errors.join(', ') })
+ end
+
def single_form_enabled?
Flipper.enabled?(:profile_show_direct_deposit_single_form, @current_user)
end
@@ -56,12 +71,13 @@ def client
@client ||= DirectDeposit::Client.new(@current_user.icn)
end
- def payment_account
- @payment_account ||= Lighthouse::DirectDeposit::PaymentAccount.new(payment_account_params)
+ def set_payment_account(params)
+ @payment_account ||= Lighthouse::DirectDeposit::PaymentAccount.new(params)
end
- def control_information
- @control_information ||= Lighthouse::DirectDeposit::ControlInformation.new(control_info_params)
+ def set_control_information(params)
+ @control_information ||= Lighthouse::DirectDeposit::ControlInformation.new
+ @control_information.assign_attributes(params)
end
def payment_account_params
@@ -84,7 +100,7 @@ def control_info_params
:has_no_fiduciary_assigned,
:is_not_deceased,
:has_payment_address,
- :has_indentity)
+ :has_identity)
end
def send_confirmation_email
diff --git a/app/models/form526_submission.rb b/app/models/form526_submission.rb
index 0bf2c58178f..cdead1058f0 100644
--- a/app/models/form526_submission.rb
+++ b/app/models/form526_submission.rb
@@ -18,7 +18,8 @@ class Form526Submission < ApplicationRecord
state :unprocessed, initial: true
state :delivered_to_primary, :failed_primary_delivery, :rejected_by_primary,
:delivered_to_backup, :failed_backup_delivery, :rejected_by_backup,
- :in_remediation, :finalized_as_successful, :unprocessable
+ :in_remediation, :finalized_as_successful, :unprocessable,
+ :processed_in_batch_remediation, :ignorable_duplicate
# - a submission has been delivered to our happy path
# - requires polling to finalize
@@ -62,7 +63,6 @@ class Form526Submission < ApplicationRecord
transitions to: :in_remediation
end
- # TODO: add this transition when we add 526 completion polling
# - The only state that means we no longer own completion of this submission
# - There is nothing more to do. E.G.
# - VBMS has accepted and returned the applicable status to us via
@@ -78,6 +78,33 @@ class Form526Submission < ApplicationRecord
event :mark_as_unprocessable do
transitions to: :unprocessable
end
+
+ # A special state to indicate this was part of our remediation 'batching'
+ # process in 2023. These were handled manually and are distinct from `in_remediation`
+ # in that they were not tracked at the time of remediation, but rather later in
+ # the 2024 526 State audit.
+ #
+ # This state is useful to us at the time of creation, but may be something
+ # to flatten to a simple `finalized_as_successful` in the future.
+ event :process_in_batch_remediation do
+ transitions to: :processed_in_batch_remediation
+ end
+
+ # A special state to indicate this was part of our remediation 'batching'
+ # process in 2023. These submissions may have been processed or not, but
+ # we don't care because they have an earlier, successful duplicate.
+ #
+ # Duplicates are identified by comparing form_json, using this script:
+ # https://github.com/department-of-veterans-affairs/va.gov-team-sensitive/blob/master/teams/benefits/scripts/526/submission_deduper.rb
+ # The result of this script can be evaluated by a qualified stakeholder to make
+ # a judgement call on whether or not a submission is a 'perfect' duplicate.
+ #
+ # IF a submission is found to be an exact duplicate of another
+ # AND its duplicate was previously submitted / remediated successfully
+ # THEN we can ignore it as a duplicate
+ event :ignore_as_duplicate do
+ transitions to: :ignorable_duplicate
+ end
end
wrap_with_logging(:start_evss_submission_job,
diff --git a/app/models/form_profile.rb b/app/models/form_profile.rb
index 17531b9e535..5743ba9e9f3 100644
--- a/app/models/form_profile.rb
+++ b/app/models/form_profile.rb
@@ -101,7 +101,8 @@ class FormProfile
vre_readiness: ['28-1900'],
coe: ['26-1880'],
adapted_housing: ['26-4555'],
- intent_to_file: ['21-0966']
+ intent_to_file: ['21-0966'],
+ ivc_champva: ['10-7959F-1']
}.freeze
FORM_ID_TO_CLASS = {
@@ -138,7 +139,8 @@ class FormProfile
'22-1990EZ' => ::FormProfiles::VA1990ez,
'26-1880' => ::FormProfiles::VA261880,
'26-4555' => ::FormProfiles::VA264555,
- '21-0966' => ::FormProfiles::VA210966
+ '21-0966' => ::FormProfiles::VA210966,
+ '10-7959F-1' => ::FormProfiles::VA107959f1
}.freeze
APT_REGEX = /\S\s+((apt|apartment|unit|ste|suite).+)/i
diff --git a/app/models/form_profiles/va_107959f1.rb b/app/models/form_profiles/va_107959f1.rb
new file mode 100644
index 00000000000..407f42714c6
--- /dev/null
+++ b/app/models/form_profiles/va_107959f1.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class FormProfiles::VA107959f1 < FormProfile
+ FORM_ID = '10-7959F-1'
+
+ def metadata
+ {
+ version: 0,
+ prefill: true,
+ returnUrl: '/review-and-submit'
+ }
+ end
+end
diff --git a/config/features.yml b/config/features.yml
index b2d1e65cd66..0c01b8fddfa 100644
--- a/config/features.yml
+++ b/config/features.yml
@@ -730,6 +730,9 @@ features:
actor_type: user
description: Enables/disables refill-related content for Medications on VA.gov
enable_in_development: true
+ mhv_landing_page_enable_va_gov_health_tools_links:
+ actor_type: user
+ description: Enables VA.gov Health Tools links (Appts, SM, Rx, Records) on MHV-on-VA.gov Landing Page
mhv_to_logingov_account_transition:
actor_type: cookie_id
description: Enables/disables MHV to Login.gov account transfer experience (Identity)
diff --git a/config/form_profile_mappings/10-7959F-1.yml b/config/form_profile_mappings/10-7959F-1.yml
new file mode 100644
index 00000000000..f9846dcb65e
--- /dev/null
+++ b/config/form_profile_mappings/10-7959F-1.yml
@@ -0,0 +1,22 @@
+
+veteran:
+ date_of_birth: [identity_information, date_of_birth]
+ full_name: [identity_information, full_name]
+ first: [identity_information, first]
+ middle: [identity_information, middle]
+ last: [identity_information, last]
+physical_address:
+ country: [contact_information, country]
+ street: [contact_information, street]
+ city: [contact_information, city]
+ state: [contact_information, state]
+ postal_code: [contact_information, postal_code]
+mailing_address:
+ country: [contact_information, country]
+ street: [contact_information, street]
+ city: [contact_information, city]
+ state: [contact_information, state]
+ postal_code: [contact_information, postal_code]
+ssn: [identity_information, ssn]
+phone_number: [contact_information, us_phone]
+email_address: [contact_information, email]
\ No newline at end of file
diff --git a/config/settings.yml b/config/settings.yml
index b069fd69ac7..c1cd8bdb74f 100644
--- a/config/settings.yml
+++ b/config/settings.yml
@@ -404,6 +404,9 @@ adapted_housing:
intent_to_file:
prefill: true
+ivc_champva:
+ prefill: true
+
# Settings for Expiry Scanner
expiry_scanner:
slack:
diff --git a/lib/evss/disability_compensation_form/data_translation_all_claim.rb b/lib/evss/disability_compensation_form/data_translation_all_claim.rb
index 8eda0195f33..dd7b695d1a0 100644
--- a/lib/evss/disability_compensation_form/data_translation_all_claim.rb
+++ b/lib/evss/disability_compensation_form/data_translation_all_claim.rb
@@ -62,6 +62,7 @@ def translate
output_form.update(translate_veteran)
output_form.update(translate_treatments)
output_form.update(translate_disabilities)
+ output_form.update(add_toxic_exposure) if Flipper.enabled?(:disability_526_toxic_exposure, @current_user)
@translated_form
end
@@ -629,6 +630,14 @@ def map_secondary(input_disability, disabilities)
end
end
+ ###
+ # Toxic Exposure
+ ###
+
+ def add_toxic_exposure
+ { 'toxicExposure' => input_form['toxicExposure'] }
+ end
+
def application_expiration_date
1.year.from_now.iso8601
end
diff --git a/lib/lighthouse/benefits_claims/configuration.rb b/lib/lighthouse/benefits_claims/configuration.rb
index 394611f02d8..72e714d2f80 100644
--- a/lib/lighthouse/benefits_claims/configuration.rb
+++ b/lib/lighthouse/benefits_claims/configuration.rb
@@ -13,7 +13,7 @@ module BenefitsClaims
class Configuration < Common::Client::Configuration::REST
self.read_timeout = Settings.lighthouse.benefits_claims.timeout || 20
- API_SCOPES = %w[system/claim.read system/claim.write].freeze
+ API_SCOPES = %w[system/claim.read system/claim.write system/526-pdf.override].freeze
CLAIMS_PATH = 'services/claims/v2/veterans'
TOKEN_PATH = 'oauth2/claims/system/v1/token'
diff --git a/lib/lighthouse/benefits_claims/service.rb b/lib/lighthouse/benefits_claims/service.rb
index 46f200a43ea..57a8f83f54b 100644
--- a/lib/lighthouse/benefits_claims/service.rb
+++ b/lib/lighthouse/benefits_claims/service.rb
@@ -102,7 +102,8 @@ def create_intent_to_file(type, claimant_ssn, lighthouse_client_id = nil, lighth
handle_error(e, lighthouse_client_id, endpoint)
end
- # submit form526 to Lighthouse API endpoint: /services/claims/v2/veterans/{veteranId}/526
+ # submit form526 to Lighthouse API endpoint: /services/claims/v2/veterans/{veteranId}/526 or
+ # /services/claims/v2/veterans/{veteranId}/526/generatePdf
# @param [hash || Requests::Form526] body: a hash representing the form526
# attributes in the Lighthouse request schema
# @param [string] lighthouse_client_id: the lighthouse_client_id requested from Lighthouse
@@ -111,28 +112,31 @@ def create_intent_to_file(type, claimant_ssn, lighthouse_client_id = nil, lighth
# @option options [hash] :body_only only return the body from the request
# @option options [string] :aud_claim_url option to override the aud_claim_url for LH Veteran Verification APIs
# @option options [hash] :auth_params a hash to send in auth params to create the access token
+ # @option options [hash] :generate_pdf call the generatePdf endpoint to receive the 526 pdf
def submit526(body, lighthouse_client_id = nil, lighthouse_rsa_key_path = nil, options = {})
- endpoint = 'benefits_claims/form/526'
+ endpoint = '{icn}/526'
path = "#{@icn}/526"
+ if options[:generate_pdf].present?
+ path += '/generatePDF/minimum-validations'
+ endpoint += '/generatePDF/minimum-validations'
+ end
+
# if we're coming straight from the transformation service without
# making this a jsonapi request body first ({data: {type:, attributes}}),
# this will put it in the correct format for transmission
- body = {
- data: {
- type: 'form/526',
- attributes: body
- }
- }.as_json.deep_transform_keys { |k| k.camelize(:lower) }
+ body = build_request_body(body)
# Inflection settings force 'current_va_employee' to render as 'currentVAEmployee' in the above camelize() call
# Since Lighthouse needs 'currentVaEmployee', the following workaround renames it.
fix_current_va_employee(body)
+ json_body = remove_unicode_characters(body)
+
response = config.post(
path,
- body,
+ json_body,
lighthouse_client_id, lighthouse_rsa_key_path, options
)
@@ -143,6 +147,26 @@ def submit526(body, lighthouse_client_id = nil, lighthouse_rsa_key_path = nil, o
private
+ def build_request_body(body)
+ {
+ data: {
+ type: 'form/526',
+ attributes: body
+ }
+ }.as_json.deep_transform_keys { |k| k.camelize(:lower) }
+ end
+
+ # this gsubbing is to fix an issue where the service that generates the 526PDF was failing due to
+ # unicoded carriage returns:
+ # i.e.: \n was throwing: "U+000A ('controlLF') is not available in the font Helvetica, encoding: WinAnsiEncoding"
+ def remove_unicode_characters(body)
+ body.to_json
+ .gsub('\\n', ' ')
+ .gsub('\\r', ' ')
+ .gsub('\\\\n', ' ')
+ .gsub('\\\\r', ' ')
+ end
+
def fix_current_va_employee(body)
if body.dig('data', 'attributes', 'veteranIdentification')&.select do |field|
field['currentVAEmployee']
diff --git a/lib/lighthouse/direct_deposit/control_information.rb b/lib/lighthouse/direct_deposit/control_information.rb
index 4ed67551aeb..a41dc0c42c9 100644
--- a/lib/lighthouse/direct_deposit/control_information.rb
+++ b/lib/lighthouse/direct_deposit/control_information.rb
@@ -3,58 +3,88 @@
module Lighthouse
module DirectDeposit
class ControlInformation
- include ActiveModel::Model
-
- ACTIONS = [:can_update_direct_deposit].freeze
- USAGES = %i[is_corp_available is_edu_claim_available].freeze
- RESTRICTIONS = %i[
- is_corp_rec_found
- has_no_bdn_payments
- has_identity
- has_index
- is_competent
- has_mailing_address
- has_no_fiduciary_assigned
- is_not_deceased
- has_payment_address
- ].freeze
-
- attr_accessor(*(ACTIONS + USAGES + RESTRICTIONS))
+ include ActiveModel::Attributes
+ include ActiveModel::AttributeAssignment
+
+ # Actions
+ attribute :can_update_direct_deposit, :boolean
+
+ # Usage
+ attribute :is_corp_available, :boolean
+ attribute :is_edu_claim_available, :boolean
+
+ # Restrictions
+ attribute :is_corp_rec_found, :boolean
+ attribute :has_no_bdn_payments, :boolean
+ attribute :has_identity, :boolean
+ attribute :has_index, :boolean
+ attribute :is_competent, :boolean
+ attribute :has_mailing_address, :boolean
+ attribute :has_no_fiduciary_assigned, :boolean
+ attribute :is_not_deceased, :boolean
+ attribute :has_payment_address, :boolean
+
attr_reader :errors
alias :comp_and_pen? is_corp_available
alias :edu_benefits? is_edu_claim_available
def account_updatable?
- @can_update_direct_deposit && restrictions.size.zero?
+ can_update_direct_deposit.present? && restrictions.size.zero?
end
def benefit_type?
comp_and_pen? || edu_benefits?
end
+ def benefit_type
+ return 'both' if comp_and_pen? && edu_benefits?
+ return 'cnp' if comp_and_pen?
+ return 'edu' if edu_benefits?
+
+ 'none'
+ end
+
def restrictions
- RESTRICTIONS.reject { |name| send(name) }
+ restrictions = []
+ restrictions << 'is_corp_rec_found' unless is_corp_rec_found
+ restrictions << 'has_no_bdn_payments' unless has_no_bdn_payments
+ restrictions << 'has_identity' unless has_identity
+ restrictions << 'has_index' unless has_index
+ restrictions << 'is_competent' unless is_competent
+ restrictions << 'has_mailing_address' unless has_mailing_address
+ restrictions << 'has_no_fiduciary_assigned' unless has_no_fiduciary_assigned
+ restrictions << 'is_not_deceased' unless is_not_deceased
+ restrictions << 'has_payment_address' unless has_payment_address
+ restrictions
end
def clear_restrictions
- @can_update_direct_deposit = true
- RESTRICTIONS.each { |name| send("#{name}=", true) }
+ assign_attributes can_update_direct_deposit: true
+ assign_attributes is_corp_rec_found: true
+ assign_attributes has_no_bdn_payments: true
+ assign_attributes has_identity: true
+ assign_attributes has_index: true
+ assign_attributes is_competent: true
+ assign_attributes has_mailing_address: true
+ assign_attributes has_no_fiduciary_assigned: true
+ assign_attributes is_not_deceased: true
+ assign_attributes has_payment_address: true
end
def valid?
@errors = []
error = 'Has restrictions. Account should not be updatable.'
- errors << error if @can_update_direct_deposit && restrictions.any?
+ @errors << error if can_update_direct_deposit && restrictions.any?
error = 'Has no restrictions. Account should be updatable.'
- errors << error if !@can_update_direct_deposit && restrictions.empty?
+ @errors << error if !can_update_direct_deposit && restrictions.empty?
error = 'Missing benefit type. Must be either CnP or EDU benefits.'
- errors << error unless benefit_type?
+ @errors << error unless benefit_type?
- errors.size.zero?
+ @errors.size.zero?
end
end
end
diff --git a/lib/pdf_fill/forms/va21p530v2.rb b/lib/pdf_fill/forms/va21p530v2.rb
index f3ab58cdec1..2dd78c06b2b 100644
--- a/lib/pdf_fill/forms/va21p530v2.rb
+++ b/lib/pdf_fill/forms/va21p530v2.rb
@@ -619,6 +619,14 @@ def expand_cemetery_location
@form_data['stateCemeteryOrTribalTrustZip'] = cemetery_location['zip'] if cemetery_location['zip'].present?
end
+ def expand_tribal_land_location
+ cemetery_location = @form_data['tribalLandLocation']
+ return if cemetery_location.blank?
+
+ @form_data['stateCemeteryOrTribalTrustName'] = cemetery_location['name'] if cemetery_location['name'].present?
+ @form_data['stateCemeteryOrTribalTrustZip'] = cemetery_location['zip'] if cemetery_location['zip'].present?
+ end
+
# VA file number can be up to 10 digits long; An optional leading 'c' or 'C' followed by
# 7-9 digits. The file number field on the 4142 form has space for 9 characters so trim the
# potential leading 'c' to ensure the file number will fit into the form without overflow.
@@ -654,7 +662,7 @@ def expand_confirmation_question
def expand_location_question
cemetery_location = @form_data['cemetaryLocationQuestion']
@form_data['cemetaryLocationQuestionCemetery'] = select_checkbox(cemetery_location == 'cemetery')
- @form_data['cemetaryLocationQuestionTribal'] = select_checkbox(cemetery_location == 'tribal')
+ @form_data['cemetaryLocationQuestionTribal'] = select_checkbox(cemetery_location == 'tribalLand')
@form_data['cemetaryLocationQuestionNone'] = select_checkbox(cemetery_location == 'none')
end
@@ -718,6 +726,7 @@ def merge_fields(_options = {})
end
expand_cemetery_location
+ expand_tribal_land_location
# special case: the UI only has a 'yes' checkbox, so the PDF 'noTransportation' checkbox can never be true.
@form_data['hasTransportation'] = @form_data['transportation'] == true ? 'YES' : nil
diff --git a/modules/ask_va_api/app/controllers/ask_va_api/v0/inquiries_controller.rb b/modules/ask_va_api/app/controllers/ask_va_api/v0/inquiries_controller.rb
index 28b3dbf113f..12f91508ed1 100644
--- a/modules/ask_va_api/app/controllers/ask_va_api/v0/inquiries_controller.rb
+++ b/modules/ask_va_api/app/controllers/ask_va_api/v0/inquiries_controller.rb
@@ -6,7 +6,7 @@ class InquiriesController < ApplicationController
around_action :handle_exceptions
before_action :get_inquiries_by_icn, only: [:index]
before_action :get_inquiry_by_id, only: [:show]
- skip_before_action :authenticate, only: %i[unauth_create upload_attachment test_create]
+ skip_before_action :authenticate, only: %i[unauth_create upload_attachment test_create show]
skip_before_action :verify_authenticity_token, only: %i[unauth_create upload_attachment test_create]
def index
@@ -26,12 +26,12 @@ def test_create
end
def create
- response = Inquiries::Creator.new(icn: current_user.icn).call(params: inquiry_params)
+ response = Inquiries::Creator.new(icn: current_user.icn).call(payload: inquiry_params)
render json: response.to_json, status: :created
end
def unauth_create
- response = Inquiries::Creator.new(icn: nil).call(params: inquiry_params)
+ response = Inquiries::Creator.new(icn: nil).call(payload: inquiry_params)
render json: response.to_json, status: :created
end
@@ -63,6 +63,8 @@ def create_reply
private
def get_inquiry_by_id
+ entity_class = AskVAApi::Inquiries::Entity
+ retriever = Inquiries::Retriever.new(user_mock_data: params[:mock], entity_class:)
inq = retriever.fetch_by_id(id: params[:id])
@inquiry = Result.new(payload: Inquiries::Serializer.new(inq).serializable_hash, status: :ok)
end
@@ -101,7 +103,7 @@ def inquiry_params
*dependant_parameters,
*submitter_parameters,
*veteran_parameters,
- school_obj: school_parameters
+ SchoolObj: school_parameters
).to_h
end
@@ -112,7 +114,7 @@ def base_parameters
InquiryCategory InquirySource InquirySubtopic InquirySummary InquiryTopic
InquiryType IsVAEmployee IsVeteran IsVeteranAnEmployee IsVeteranDeceased
LevelOfAuthentication MedicalCenter MiddleName PreferredName Pronouns
- StreetAddress2 SupervisorFlag VaEmployeeTimeStamp ZipCode
+ StreetAddress2 SupervisorFlag VaEmployeeTimeStamp ZipCode Suffix
]
end
@@ -130,7 +132,7 @@ def submitter_parameters
Submitter SubmitterDependent SubmitterDOB SubmitterGender SubmitterProvince
SubmitterSSN SubmitterState SubmitterStateOfResidency SubmitterStateOfSchool
SubmitterStateProperty SubmitterStreetAddress SubmitterVetCenter
- SubmitterZipCodeOfResidency SubmitterQuestion
+ SubmitterZipCodeOfResidency SubmitterQuestion SubmittersDodIdEdipiNumber
]
end
@@ -143,7 +145,7 @@ def veteran_parameters
VeteranRelationship VeteranServiceEndDate VeteranServiceNumber
VeteranServiceStartDate VeteranSSN VeteransState VeteranStreetAddress
VeteranSuffix VeteranSuiteAptOther VeteranZipCode WhoWasTheirCounselor
- YourLastName
+ YourLastName VeteranDodIdEdipiNumber
]
end
diff --git a/modules/ask_va_api/app/lib/ask_va_api/correspondences/creator.rb b/modules/ask_va_api/app/lib/ask_va_api/correspondences/creator.rb
index 9cdf1ad1759..3e57c1fd81a 100644
--- a/modules/ask_va_api/app/lib/ask_va_api/correspondences/creator.rb
+++ b/modules/ask_va_api/app/lib/ask_va_api/correspondences/creator.rb
@@ -35,7 +35,8 @@ def post_data(payload: {})
def handle_response_data(response)
if response[:Data].nil?
- raise CorrespondencesCreatorError, response[:Message]
+ error = JSON.parse(response[:body], symbolize_names: true)
+ raise CorrespondencesCreatorError, error[:Message]
else
response[:Data]
end
diff --git a/modules/ask_va_api/app/lib/ask_va_api/inquiries/creator.rb b/modules/ask_va_api/app/lib/ask_va_api/inquiries/creator.rb
index dbd8e4e7ef0..918601ea690 100644
--- a/modules/ask_va_api/app/lib/ask_va_api/inquiries/creator.rb
+++ b/modules/ask_va_api/app/lib/ask_va_api/inquiries/creator.rb
@@ -13,8 +13,8 @@ def initialize(icn:, service: nil)
@service = service || default_service
end
- def call(params:)
- post_data(payload: { params: })
+ def call(payload:)
+ post_data(payload:)
rescue => e
ErrorHandler.handle_service_error(e)
end
@@ -32,7 +32,8 @@ def post_data(payload: {})
def handle_response_data(response)
if response[:Data].nil?
- raise InquiriesCreatorError, response[:Message]
+ error = JSON.parse(response[:body], symbolize_names: true)
+ raise InquiriesCreatorError, error[:Message]
else
response[:Data]
end
diff --git a/modules/ask_va_api/app/lib/ask_va_api/inquiries/retriever.rb b/modules/ask_va_api/app/lib/ask_va_api/inquiries/retriever.rb
index 0951d724eb8..073c35f8832 100644
--- a/modules/ask_va_api/app/lib/ask_va_api/inquiries/retriever.rb
+++ b/modules/ask_va_api/app/lib/ask_va_api/inquiries/retriever.rb
@@ -57,7 +57,12 @@ def filter_data(data, id = nil)
end
def handle_response_data(response)
- response[:Data].presence || raise(InquiriesRetrieverError, response[:Message])
+ if response[:Data].nil?
+ error = JSON.parse(response[:body], symbolize_names: true)
+ raise InquiriesRetrieverError, error[:Message]
+ else
+ response[:Data]
+ end
end
end
end
diff --git a/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/creator_spec.rb b/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/creator_spec.rb
index 6136b5c1609..bea0c25bd50 100644
--- a/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/creator_spec.rb
+++ b/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/creator_spec.rb
@@ -22,9 +22,23 @@ module Correspondences
end
context 'when not successful' do
+ let(:body) do
+ '{"Data":null,"Message":"Data Validation: Missing Reply"' \
+ ',"ExceptionOccurred":true,"ExceptionMessage":"Data Validation: ' \
+ 'Missing Reply","MessageId":"e2cbe041-df91-41f4-8bd2-8b6d9dbb2e38"}'
+ end
+ let(:failure) do
+ {
+ status: 400,
+ body:,
+ response_headers: nil,
+ url: nil
+ }
+ end
+
before do
allow_any_instance_of(Crm::CrmToken).to receive(:call).and_return('Token')
- allow_any_instance_of(Crm::Service).to receive(:call).and_return({ Data: nil, Message: 'Error has occur' })
+ allow_any_instance_of(Crm::Service).to receive(:call).and_return(failure)
end
it 'raise CorrespondenceCreatorError' do
diff --git a/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/creator_spec.rb b/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/creator_spec.rb
index 6bb4e6d651b..793ebba7057 100644
--- a/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/creator_spec.rb
+++ b/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/creator_spec.rb
@@ -6,7 +6,7 @@
let(:icn) { '123456' }
let(:service) { instance_double(Crm::Service) }
let(:creator) { described_class.new(icn:, service:) }
- let(:params) { { FirstName: 'Fake', YourLastName: 'Smith' } }
+ let(:payload) { { FirstName: 'Fake', YourLastName: 'Smith' } }
let(:endpoint) { AskVAApi::Inquiries::Creator::ENDPOINT }
before do
@@ -17,35 +17,45 @@
context 'when the API call is successful' do
before do
allow(service).to receive(:call).with(endpoint:, method: :put,
- payload: { params: }).and_return({
- Data: {
- InquiryNumber: '530d56a8-affd-ee11' \
- '-a1fe-001dd8094ff1'
- },
- Message: '',
- ExceptionOccurred: false,
- ExceptionMessage: '',
- MessageId: 'b8ebd8e7-3bbf-49c5' \
- '-aff0-99503e50ee27'
- })
+ payload:).and_return({
+ Data: {
+ InquiryNumber: '530d56a8-affd-ee11' \
+ '-a1fe-001dd8094ff1'
+ },
+ Message: '',
+ ExceptionOccurred: false,
+ ExceptionMessage: '',
+ MessageId: 'b8ebd8e7-3bbf-49c5' \
+ '-aff0-99503e50ee27'
+ })
end
it 'posts data to the service and returns the response' do
- expect(creator.call(params:)).to eq({ InquiryNumber: '530d56a8-affd-ee11-a1fe-001dd8094ff1' })
+ expect(creator.call(payload:)).to eq({ InquiryNumber: '530d56a8-affd-ee11-a1fe-001dd8094ff1' })
end
end
context 'when the API call fails' do
+ let(:body) do
+ '{"Data":null,"Message":"Data Validation: missing InquiryCategory"' \
+ ',"ExceptionOccurred":true,"ExceptionMessage":"Data Validation: missing' \
+ 'InquiryCategory","MessageId":"cb0dd954-ef25-4e56-b0d9-41925e5a190c"}'
+ end
+ let(:failure) do
+ {
+ status: 400,
+ body:,
+ response_headers: nil,
+ url: nil
+ }
+ end
+
before do
- allow(service).to receive(:call).and_return({ Data: nil,
- Message: 'Data Validation: missing InquiryCategory',
- ExceptionOccurred: true,
- ExceptionMessage: 'Data Validation: missing InquiryCategory',
- MessageId: '13bc59ea-c90a-4d48-8979-fe71e0f7ddeb' })
+ allow(service).to receive(:call).and_return(failure)
end
it 'raise InquiriesCreatorError' do
- expect { creator.call(params:) }.to raise_error(ErrorHandler::ServiceError)
+ expect { creator.call(payload:) }.to raise_error(ErrorHandler::ServiceError)
end
end
end
diff --git a/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/retriever_spec.rb b/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/retriever_spec.rb
index b848c81cb93..ee1f4e45987 100644
--- a/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/retriever_spec.rb
+++ b/modules/ask_va_api/spec/app/lib/ask_va_api/inquiries/retriever_spec.rb
@@ -20,17 +20,23 @@
describe '#call' do
context 'when Crm raise an error' do
let(:icn) { '123' }
- let(:response) do
- { Data: nil,
- Message: 'Data Validation: No Contact found by ICN',
- ExceptionOccurred: true,
- ExceptionMessage: 'Data Validation: No Contact found by ICN',
- MessageId: '2733ca25-7e64-4fbc-af2c-366f4bd2e3dc' }
+ let(:body) do
+ '{"Data":null,"Message":"Data Validation: No Inquiries found by ID A-20240423-30709"' \
+ ',"ExceptionOccurred":true,"ExceptionMessage":"Data Validation: No Inquiries found by ' \
+ 'ID A-20240423-30709","MessageId":"ca5b990a-63fe-407d-a364-46caffce12c1"}'
+ end
+ let(:failure) do
+ {
+ status: 400,
+ body:,
+ response_headers: nil,
+ url: nil
+ }
end
before do
allow_any_instance_of(Crm::CrmToken).to receive(:call).and_return('Token')
- allow(service).to receive(:call).and_return(response)
+ allow(service).to receive(:call).and_return(failure)
end
it 'raise CorrespondenceRetrieverrError' do
diff --git a/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb b/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb
index 111e5fe58fb..03eec8510ca 100644
--- a/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb
+++ b/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb
@@ -207,19 +207,25 @@
end
context 'when the id is invalid' do
- let(:crm_response) do
- { Data: nil,
- Message: 'Data Validation: No Inquiries found by ID A-20230305-30617',
- ExceptionOccurred: true,
- ExceptionMessage: 'Data Validation: No Inquiries found by ID A-20230305-30617',
- MessageId: 'e6024ccb-e19b-4bc6-990c-667e7ebab4ec' }
+ let(:body) do
+ '{"Data":null,"Message":"Data Validation: No Inquiries found by ID A-20240423-30709"' \
+ ',"ExceptionOccurred":true,"ExceptionMessage":"Data Validation: No Inquiries found by ' \
+ 'ID A-20240423-30709","MessageId":"ca5b990a-63fe-407d-a364-46caffce12c1"}'
+ end
+ let(:failure) do
+ {
+ status: 400,
+ body:,
+ response_headers: nil,
+ url: nil
+ }
end
let(:service) { instance_double(Crm::Service) }
before do
allow(Crm::Service).to receive(:new).and_return(service)
allow_any_instance_of(Crm::CrmToken).to receive(:call).and_return('Token')
- allow(service).to receive(:call).and_return(crm_response)
+ allow(service).to receive(:call).and_return(failure)
sign_in(authorized_user)
get "#{inquiry_path}/#{invalid_id}"
end
@@ -228,17 +234,9 @@
it_behaves_like 'common error handling', :unprocessable_entity, 'service_error',
'AskVAApi::Inquiries::InquiriesRetrieverError: ' \
- 'Data Validation: No Inquiries found by ID A-20230305-30617'
+ 'Data Validation: No Inquiries found by ID A-20240423-30709'
end
end
-
- context 'when user is not signed in' do
- before do
- get "#{inquiry_path}/#{valid_id}"
- end
-
- it { expect(response).to have_http_status(:unauthorized) }
- end
end
describe 'GET #download_attachment' do
@@ -332,24 +330,24 @@
end
describe 'POST #create' do
- let(:params) { { FirstName: 'Fake', YourLastName: 'Smith' } }
+ let(:payload) { { FirstName: 'Fake', YourLastName: 'Smith' } }
let(:endpoint) { AskVAApi::Inquiries::Creator::ENDPOINT }
context 'when successful' do
before do
allow_any_instance_of(Crm::Service).to receive(:call)
.with(endpoint:, method: :put,
- payload: { params: }).and_return({
- Data: {
- Id: '530d56a8-affd-ee11-a1fe-001dd8094ff1'
- },
- Message: '',
- ExceptionOccurred: false,
- ExceptionMessage: '',
- MessageId: 'b8ebd8e7-3bbf-49c5-aff0-99503e50ee27'
- })
+ payload:).and_return({
+ Data: {
+ Id: '530d56a8-affd-ee11-a1fe-001dd8094ff1'
+ },
+ Message: '',
+ ExceptionOccurred: false,
+ ExceptionMessage: '',
+ MessageId: 'b8ebd8e7-3bbf-49c5-aff0-99503e50ee27'
+ })
sign_in(authorized_user)
- post '/ask_va_api/v0/inquiries/auth', params:
+ post '/ask_va_api/v0/inquiries/auth', params: payload
end
it { expect(response).to have_http_status(:created) }
@@ -357,16 +355,26 @@
context 'when crm api fail' do
context 'when the API call fails' do
+ let(:body) do
+ '{"Data":null,"Message":"Data Validation: missing InquiryCategory"' \
+ ',"ExceptionOccurred":true,"ExceptionMessage":"Data Validation: missing' \
+ 'InquiryCategory","MessageId":"cb0dd954-ef25-4e56-b0d9-41925e5a190c"}'
+ end
+ let(:failure) do
+ {
+ status: 400,
+ body:,
+ response_headers: nil,
+ url: nil
+ }
+ end
+
before do
allow_any_instance_of(Crm::Service).to receive(:call)
.with(endpoint:, method: :put,
- payload: { params: }).and_return({ Data: nil,
- Message: 'Data Validation: missing InquiryCategory',
- ExceptionOccurred: true,
- ExceptionMessage: 'Data Validation: missing InquiryCategory',
- MessageId: '13bc59ea-c90a-4d48-8979-fe71e0f7ddeb' })
+ payload:).and_return(failure)
sign_in(authorized_user)
- post '/ask_va_api/v0/inquiries/auth', params:
+ post '/ask_va_api/v0/inquiries/auth', params: payload
end
it 'raise InquiriesCreatorError' do
@@ -380,23 +388,23 @@
end
describe 'POST #unauth_create' do
- let(:params) { { FirstName: 'Fake', YourLastName: 'Smith' } }
+ let(:payload) { { FirstName: 'Fake', YourLastName: 'Smith' } }
let(:endpoint) { AskVAApi::Inquiries::Creator::ENDPOINT }
context 'when successful' do
before do
allow_any_instance_of(Crm::Service).to receive(:call)
.with(endpoint:, method: :put,
- payload: { params: }).and_return({
- Data: {
- Id: '530d56a8-affd-ee11-a1fe-001dd8094ff1'
- },
- Message: '',
- ExceptionOccurred: false,
- ExceptionMessage: '',
- MessageId: 'b8ebd8e7-3bbf-49c5-aff0-99503e50ee27'
- })
- post inquiry_path, params:
+ payload:).and_return({
+ Data: {
+ Id: '530d56a8-affd-ee11-a1fe-001dd8094ff1'
+ },
+ Message: '',
+ ExceptionOccurred: false,
+ ExceptionMessage: '',
+ MessageId: 'b8ebd8e7-3bbf-49c5-aff0-99503e50ee27'
+ })
+ post inquiry_path, params: payload
end
it { expect(response).to have_http_status(:created) }
@@ -404,15 +412,25 @@
context 'when crm api fail' do
context 'when the API call fails' do
+ let(:body) do
+ '{"Data":null,"Message":"Data Validation: missing InquiryCategory"' \
+ ',"ExceptionOccurred":true,"ExceptionMessage":"Data Validation: missing' \
+ 'InquiryCategory","MessageId":"cb0dd954-ef25-4e56-b0d9-41925e5a190c"}'
+ end
+ let(:failure) do
+ {
+ status: 400,
+ body:,
+ response_headers: nil,
+ url: nil
+ }
+ end
+
before do
allow_any_instance_of(Crm::Service).to receive(:call)
.with(endpoint:, method: :put,
- payload: { params: }).and_return({ Data: nil,
- Message: 'Data Validation: missing InquiryCategory',
- ExceptionOccurred: true,
- ExceptionMessage: 'Data Validation: missing InquiryCategory',
- MessageId: '13bc59ea-c90a-4d48-8979-fe71e0f7ddeb' })
- post '/ask_va_api/v0/inquiries', params:
+ payload:).and_return(failure)
+ post '/ask_va_api/v0/inquiries', params: payload
end
it 'raise InquiriesCreatorError' do
@@ -472,7 +490,7 @@ def json_response
describe 'POST #test_create' do
before do
- allow_any_instance_of(Crm::Service).to receive(:call).and_return({ message: 'success' })
+ allow_any_instance_of(Crm::Service).to receive(:call).and_return({ body: { message: 'success' } })
post '/ask_va_api/v0/test_create',
params: { 'reply' => 'test', 'endpoint' => 'inquiries/id/reply/new' },
as: :json
@@ -486,14 +504,50 @@ def json_response
describe 'POST #create_reply' do
let(:payload) { { 'reply' => 'this is my reply' } }
- before do
- allow_any_instance_of(Crm::Service).to receive(:call).and_return({ Data: { Id: '123' } })
- sign_in(authorized_user)
- post '/ask_va_api/v0/inquiries/123/reply/new', params: payload
+ context 'when successful' do
+ before do
+ allow_any_instance_of(Crm::Service).to receive(:call).and_return({ Data: { Id: '123' } })
+ sign_in(authorized_user)
+ post '/ask_va_api/v0/inquiries/123/reply/new', params: payload
+ end
+
+ it 'returns status 200' do
+ expect(response).to have_http_status(:ok)
+ end
end
- it 'returns status 200' do
- expect(response).to have_http_status(:ok)
+ context 'when crm api fail' do
+ context 'when the API call fails' do
+ let(:endpoint) { 'inquiries/123/reply/new' }
+ let(:body) do
+ '{"Data":null,"Message":"Data Validation: Missing Reply"' \
+ ',"ExceptionOccurred":true,"ExceptionMessage":"Data Validation: ' \
+ 'Missing Reply","MessageId":"e2cbe041-df91-41f4-8bd2-8b6d9dbb2e38"}'
+ end
+ let(:failure) do
+ {
+ status: 400,
+ body:,
+ response_headers: nil,
+ url: nil
+ }
+ end
+
+ before do
+ sign_in(authorized_user)
+ allow_any_instance_of(Crm::Service).to receive(:call)
+ .with(endpoint:, method: :put,
+ payload: { Reply: 'this is my reply' }).and_return(failure)
+ post '/ask_va_api/v0/inquiries/123/reply/new', params: payload
+ end
+
+ it 'raise InquiriesCreatorError' do
+ expect(response).to have_http_status(:unprocessable_entity)
+ end
+
+ it_behaves_like 'common error handling', :unprocessable_entity, 'service_error',
+ 'AskVAApi::Correspondences::CorrespondencesCreatorError: Data Validation: Missing Reply'
+ end
end
end
end
diff --git a/modules/check_in/app/serializers/check_in/facilities/facilities_data_serializer.rb b/modules/check_in/app/serializers/check_in/facilities/facilities_data_serializer.rb
new file mode 100644
index 00000000000..6566d04578f
--- /dev/null
+++ b/modules/check_in/app/serializers/check_in/facilities/facilities_data_serializer.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module CheckIn
+ module Facilities
+ class FacilitiesDataSerializer
+ include JSONAPI::Serializer
+
+ set_id(&:id)
+
+ attribute :name, :type, :classification, :timezone, :phone, :physicalAddress
+ end
+ end
+end
diff --git a/modules/check_in/app/services/check_in/vaos/base_service.rb b/modules/check_in/app/services/check_in/vaos/base_service.rb
index 8cf947ab968..8a906d04d98 100644
--- a/modules/check_in/app/services/check_in/vaos/base_service.rb
+++ b/modules/check_in/app/services/check_in/vaos/base_service.rb
@@ -9,13 +9,25 @@ class BaseService < Common::Client::Base
include SentryLogging
include Common::Client::Concerns::Monitoring
- attr_reader :patient_icn, :token_service
+ attr_reader :check_in_session, :patient_icn
STATSD_KEY_PREFIX = 'api.check_in.vaos'
- def initialize(patient_icn:)
- @patient_icn = patient_icn
- @token_service = CheckIn::Map::TokenService.build({ patient_icn: })
+ ##
+ # Builds a Service instance
+ #
+ # @param opts [Hash] options to create the object
+ #
+ # @return [Service] an instance of this class
+ #
+ def self.build(opts = {})
+ new(opts)
+ end
+
+ def initialize(opts)
+ @check_in_session = opts[:check_in_session]
+ @patient_icn = ::V2::Lorota::RedisClient.build.icn(uuid: check_in_session.uuid)
+
super()
end
@@ -35,6 +47,10 @@ def headers
}
end
+ def token_service
+ @token_service ||= Map::TokenService.build(patient_icn:)
+ end
+
def referrer
if Settings.hostname.ends_with?('.gov')
"https://#{Settings.hostname}".gsub('vets', 'va')
diff --git a/modules/check_in/spec/serializers/check_in/facilities/facilities_data_serializer_spec.rb b/modules/check_in/spec/serializers/check_in/facilities/facilities_data_serializer_spec.rb
new file mode 100644
index 00000000000..8dd6b7968a5
--- /dev/null
+++ b/modules/check_in/spec/serializers/check_in/facilities/facilities_data_serializer_spec.rb
@@ -0,0 +1,144 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe CheckIn::Facilities::FacilitiesDataSerializer do
+ subject { described_class }
+
+ let(:facilities_data) do
+ {
+ id: '442',
+ facilitiesApiId: 'vha_442',
+ vistaSite: '442',
+ vastParent: '442',
+ type: 'va_health_facility',
+ name: 'Cheyenne VA Medical Center',
+ classification: 'VA Medical Center (VAMC)',
+ timezone: {
+ timeZoneId: 'America/Denver'
+ },
+ lat: 41.148026,
+ long: -104.786255,
+ website: 'https://www.va.gov/cheyenne-health-care/locations/cheyenne-va-medical-center/',
+ phone: {
+ main: '307-778-7550',
+ fax: '307-778-7381',
+ pharmacy: '866-420-6337',
+ afterHours: '307-778-7550',
+ patientAdvocate: '307-778-7550 x7573',
+ mentalHealthClinic: '307-778-7349',
+ enrollmentCoordinator: '307-778-7550 x7579'
+ },
+ mailingAddress: {
+ type: 'postal',
+ line: [nil, nil, nil]
+ },
+ physicalAddress: {
+ type: 'physical',
+ line: ['2360 East Pershing Boulevard', nil, nil],
+ city: 'Cheyenne',
+ state: 'WY',
+ postalCode: '82001-5356'
+ },
+ mobile: false,
+ healthService: %w[Audiology Cardiology CaregiverSupport Covid19Vaccine DentalServices Dermatology EmergencyCare
+ Gastroenterology Gynecology MentalHealthCare Nutrition Ophthalmology Optometry Orthopedics
+ Podiatry PrimaryCare Urology WomensHealth],
+ operatingStatus: {
+ code: 'NORMAL'
+ },
+ visn: '19'
+ }
+ end
+
+ describe '#serializable_hash' do
+ context 'when all the necessary fields exist' do
+ let(:serialized_hash_response) do
+ {
+ data: {
+ id: '442',
+ type: :facilities_data,
+ attributes: {
+ type: 'va_health_facility',
+ name: 'Cheyenne VA Medical Center',
+ classification: 'VA Medical Center (VAMC)',
+ timezone: {
+ timeZoneId: 'America/Denver'
+ },
+ phone: {
+ main: '307-778-7550',
+ fax: '307-778-7381',
+ pharmacy: '866-420-6337',
+ afterHours: '307-778-7550',
+ patientAdvocate: '307-778-7550 x7573',
+ mentalHealthClinic: '307-778-7349',
+ enrollmentCoordinator: '307-778-7550 x7579'
+ },
+ physicalAddress: {
+ type: 'physical',
+ line: ['2360 East Pershing Boulevard', nil, nil],
+ city: 'Cheyenne',
+ state: 'WY',
+ postalCode: '82001-5356'
+ }
+ }
+ }
+ }
+ end
+
+ it 'returns a serialized hash' do
+ facilities_struct = OpenStruct.new(facilities_data)
+ facilities_serializer = CheckIn::Facilities::FacilitiesDataSerializer.new(facilities_struct)
+
+ expect(facilities_serializer.serializable_hash).to eq(serialized_hash_response)
+ end
+ end
+
+ context 'when name does not exist' do
+ let(:facilities_data_without_name) do
+ facilities_data.except!(:name)
+ facilities_data
+ end
+
+ let(:serialized_hash_response) do
+ {
+ data: {
+ id: '442',
+ type: :facilities_data,
+ attributes: {
+ name: nil,
+ type: 'va_health_facility',
+ classification: 'VA Medical Center (VAMC)',
+ timezone: {
+ timeZoneId: 'America/Denver'
+ },
+ phone: {
+ main: '307-778-7550',
+ fax: '307-778-7381',
+ pharmacy: '866-420-6337',
+ afterHours: '307-778-7550',
+ patientAdvocate: '307-778-7550 x7573',
+ mentalHealthClinic: '307-778-7349',
+ enrollmentCoordinator: '307-778-7550 x7579'
+ },
+ physicalAddress: {
+ type: 'physical',
+ line: ['2360 East Pershing Boulevard', nil, nil],
+ city: 'Cheyenne',
+ state: 'WY',
+ postalCode: '82001-5356'
+ }
+ }
+ }
+ }
+ end
+
+ it 'returns a serialized hash with nil in name field' do
+ facilities_struct = OpenStruct.new(facilities_data_without_name)
+ facilities_serializer = CheckIn::Facilities::FacilitiesDataSerializer.new(facilities_struct)
+
+ expect(facilities_serializer.serializable_hash).to eq(serialized_hash_response)
+ end
+ end
+ end
+end
diff --git a/modules/check_in/spec/services/check_in/map/token_service_spec.rb b/modules/check_in/spec/services/check_in/map/token_service_spec.rb
index a87429a51f1..a03e1e7b073 100644
--- a/modules/check_in/spec/services/check_in/map/token_service_spec.rb
+++ b/modules/check_in/spec/services/check_in/map/token_service_spec.rb
@@ -3,14 +3,10 @@
require 'rails_helper'
describe CheckIn::Map::TokenService do
- subject { described_class }
+ subject { described_class.build(opts) }
let(:patient_icn) { '123' }
- let(:opts) do
- {
- patient_icn:
- }
- end
+ let(:opts) { { patient_icn: } }
let(:memory_store) { ActiveSupport::Cache.lookup_store(:memory_store) }
before do
@@ -21,13 +17,13 @@
describe '.build' do
it 'returns an instance of Service' do
- expect(subject.build(opts)).to be_an_instance_of(described_class)
+ expect(subject).to be_an_instance_of(described_class)
end
end
describe '#initialize' do
it 'has a redis client' do
- expect(subject.build(opts).redis_client).to be_a(CheckIn::Map::RedisClient)
+ expect(subject.redis_client).to be_a(CheckIn::Map::RedisClient)
end
end
@@ -41,7 +37,7 @@
end
it 'returns token from redis' do
- expect(subject.build(opts).token).to eq(access_token)
+ expect(subject.token).to eq(access_token)
end
end
@@ -51,8 +47,11 @@
.and_return({ access_token:, expiration: })
end
- it 'returns token by calling client' do
- expect(subject.build(opts).token).to eq(access_token)
+ it 'returns token by calling client and saves it in redis' do
+ redis_client = subject.redis_client
+ expect(redis_client).to receive(:save_token)
+
+ expect(subject.token).to eq(access_token)
end
end
end
diff --git a/modules/check_in/spec/services/check_in/vaos/appointment_service_spec.rb b/modules/check_in/spec/services/check_in/vaos/appointment_service_spec.rb
index ca71d3cb05c..37adf918027 100644
--- a/modules/check_in/spec/services/check_in/vaos/appointment_service_spec.rb
+++ b/modules/check_in/spec/services/check_in/vaos/appointment_service_spec.rb
@@ -3,17 +3,17 @@
require 'rails_helper'
describe CheckIn::VAOS::AppointmentService do
- subject { described_class.new(patient_icn:) }
+ subject { described_class }
+ let(:uuid) { 'd602d9eb-9a31-484f-9637-13ab0b507e0d' }
+ let(:check_in_session) { CheckIn::V2::Session.build(data: { uuid: }) }
let(:patient_icn) { '123' }
let(:token) { 'test_token' }
let(:request_id) { SecureRandom.uuid }
- describe '#initialize' do
- it 'returns an instance of service' do
- service_obj = subject
- expect(service_obj).to be_an_instance_of(CheckIn::VAOS::AppointmentService)
- expect(service_obj.token_service).to be_an_instance_of(CheckIn::Map::TokenService)
+ describe '.build' do
+ it 'returns an instance of Service' do
+ expect(subject.build(check_in_session:)).to be_an_instance_of(described_class)
end
end
@@ -42,21 +42,27 @@
let(:faraday_response) { double('Faraday::Response') }
let(:faraday_env) { double('Faraday::Env', status: 200, body: appointments_response.to_json) }
+ before do
+ allow_any_instance_of(V2::Lorota::RedisClient).to receive(:icn).with(uuid:)
+ .and_return(patient_icn)
+ allow_any_instance_of(CheckIn::Map::TokenService).to receive(:token)
+ .and_return(token)
+ end
+
context 'when vaos returns successful response' do
before do
- allow_any_instance_of(CheckIn::Map::TokenService).to receive(:token)
- .and_return(token)
- allow_any_instance_of(Faraday::Connection).to receive(:get).with('/vaos/v1/patients/123/appointments',
- { start: start_date, end: end_date,
- statuses: })
- .and_return(faraday_response)
+ allow_any_instance_of(Faraday::Connection).to receive(:get)
+ .with("/vaos/v1/patients/#{patient_icn}/appointments",
+ { start: start_date, end: end_date, statuses: })
+ .and_return(faraday_response)
allow(faraday_response).to receive(:env).and_return(faraday_env)
end
it 'returns appointments' do
- response = subject.get_appointments(DateTime.parse(start_date).in_time_zone,
- DateTime.parse(end_date).in_time_zone,
- statuses)
+ svc = subject.build(check_in_session:)
+ response = svc.get_appointments(DateTime.parse(start_date).in_time_zone,
+ DateTime.parse(end_date).in_time_zone,
+ statuses)
expect(response).to eq(appointments_response)
end
end
@@ -66,8 +72,6 @@
let(:exception) { Common::Exceptions::BackendServiceException.new(nil, {}, resp.status, resp.body) }
before do
- allow_any_instance_of(CheckIn::Map::TokenService).to receive(:token)
- .and_return(token)
allow_any_instance_of(Faraday::Connection).to receive(:get).with('/vaos/v1/patients/123/appointments',
{ start: start_date, end: end_date,
statuses: })
@@ -75,10 +79,11 @@
end
it 'throws exception' do
+ svc = subject.build(check_in_session:)
expect do
- subject.get_appointments(DateTime.parse(start_date).in_time_zone,
- DateTime.parse(end_date).in_time_zone,
- statuses)
+ svc.get_appointments(DateTime.parse(start_date).in_time_zone,
+ DateTime.parse(end_date).in_time_zone,
+ statuses)
end.to(raise_error do |error|
expect(error).to be_a(Common::Exceptions::BackendServiceException)
end)
diff --git a/modules/check_in/spec/services/check_in/vaos/base_service_spec.rb b/modules/check_in/spec/services/check_in/vaos/base_service_spec.rb
index f523aab9fc6..e7733b82363 100644
--- a/modules/check_in/spec/services/check_in/vaos/base_service_spec.rb
+++ b/modules/check_in/spec/services/check_in/vaos/base_service_spec.rb
@@ -3,12 +3,35 @@
require 'rails_helper'
describe CheckIn::VAOS::BaseService do
- subject { described_class.new(patient_icn:) }
+ subject { described_class.build(check_in_session:) }
+ let(:uuid) { 'd602d9eb-9a31-484f-9637-13ab0b507e0d' }
+ let(:check_in_session) { CheckIn::V2::Session.build(data: { uuid: }) }
let(:patient_icn) { '123' }
let(:token) { 'test_token' }
let(:request_id) { SecureRandom.uuid }
+ describe '.build' do
+ it 'returns an instance of Service' do
+ expect(subject).to be_an_instance_of(described_class)
+ end
+ end
+
+ describe '#initialize' do
+ before do
+ allow_any_instance_of(V2::Lorota::RedisClient).to receive(:icn).with(uuid:)
+ .and_return(patient_icn)
+ end
+
+ it 'has a check_in_session object' do
+ expect(subject.check_in_session).to be_a(CheckIn::V2::Session)
+ end
+
+ it 'has a patient icn' do
+ expect(subject.patient_icn).to eq(patient_icn)
+ end
+ end
+
describe '#config' do
it 'returns an instance of Configuration' do
expect(subject.config).to be_an_instance_of(CheckIn::VAOS::Configuration)
@@ -17,8 +40,9 @@
describe '#headers' do
before do
- allow_any_instance_of(CheckIn::Map::TokenService).to receive(:token).and_return(token)
RequestStore.store['request_id'] = request_id
+
+ allow_any_instance_of(CheckIn::Map::TokenService).to receive(:token).and_return(token)
end
it 'returns correct headers' do
diff --git a/modules/claims_api/app/sidekiq/claims_api/claim_uploader.rb b/modules/claims_api/app/sidekiq/claims_api/claim_uploader.rb
index bc6bb6cacc0..e0a87d2c5eb 100644
--- a/modules/claims_api/app/sidekiq/claims_api/claim_uploader.rb
+++ b/modules/claims_api/app/sidekiq/claims_api/claim_uploader.rb
@@ -7,7 +7,7 @@ module ClaimsApi
class ClaimUploader < ClaimsApi::ServiceBase
sidekiq_options retry: true, unique_until: :success
- def perform(uuid)
+ def perform(uuid) # rubocop:disable Metrics/MethodLength
claim_object = ClaimsApi::SupportingDocument.find_by(id: uuid) ||
ClaimsApi::AutoEstablishedClaim.find_by(id: uuid)
@@ -21,11 +21,12 @@ def perform(uuid)
else
auth_headers = auto_claim.auth_headers
uploader = claim_object.uploader
- uploader.retrieve_from_store!(claim_object.file_data['filename'])
+ original_filename = claim_object.file_data['filename']
+ uploader.retrieve_from_store!(original_filename)
file_body = uploader.read
ClaimsApi::Logger.log('lighthouse_claim_uploader', claim_id: auto_claim.id, attachment_id: uuid)
if Flipper.enabled? :claims_claim_uploader_use_bd
- bd_upload_body(auto_claim:, file_body:, doc_type:)
+ bd_upload_body(auto_claim:, file_body:, doc_type:, original_filename:)
else
EVSS::DocumentsService.new(auth_headers).upload(file_body, claim_upload_document(claim_object))
end
@@ -34,19 +35,19 @@ def perform(uuid)
private
- def bd_upload_body(auto_claim:, file_body:, doc_type:)
+ def bd_upload_body(auto_claim:, file_body:, doc_type:, original_filename:)
fh = Tempfile.new(['pdf_path', '.pdf'], binmode: true)
begin
fh.write(file_body)
fh.close
- claim_bd_upload_document(auto_claim, doc_type, fh.path)
+ claim_bd_upload_document(auto_claim, doc_type, fh.path, original_filename)
ensure
fh.unlink
end
end
- def claim_bd_upload_document(claim, doc_type, pdf_path) # rubocop:disable Metrics/MethodLength
- ClaimsApi::BD.new.upload(claim:, doc_type:, pdf_path:)
+ def claim_bd_upload_document(claim, doc_type, pdf_path, original_filename) # rubocop:disable Metrics/MethodLength
+ ClaimsApi::BD.new.upload(claim:, doc_type:, pdf_path:, original_filename:)
# Temporary errors (returning HTML, connection timeout), retry call
rescue Faraday::ParsingError, Faraday::TimeoutError => e
message = get_error_message(e)
diff --git a/modules/claims_api/app/swagger/claims_api/v2/dev/swagger.json b/modules/claims_api/app/swagger/claims_api/v2/dev/swagger.json
index 7094044200c..bc5b78f3b26 100644
--- a/modules/claims_api/app/swagger/claims_api/v2/dev/swagger.json
+++ b/modules/claims_api/app/swagger/claims_api/v2/dev/swagger.json
@@ -967,7 +967,7 @@
"lighthouseId": null,
"maxEstClaimDate": null,
"minEstClaimDate": null,
- "status": "COMPLETE",
+ "status": "CANCELED",
"submitterApplicationCode": "EBN",
"submitterRoleCode": "VET",
"supportingDocuments": [
@@ -1625,6 +1625,7 @@
"serviceNumber": {
"type": "string",
"description": "Service identification number",
+ "maxLength": 1000,
"nullable": true
},
"veteranNumber": {
@@ -1645,6 +1646,7 @@
"type": "string",
"description": "Veteran's international phone number.",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -1687,6 +1689,7 @@
"description": "City for the Veteran's current mailing address.",
"type": "string",
"pattern": "^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -1698,6 +1701,7 @@
"country": {
"description": "Country for the Veteran's current mailing address. Must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -1783,6 +1787,7 @@
"description": "City for the Veteran's new address.",
"type": "string",
"pattern": "^$|^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -1794,6 +1799,7 @@
"country": {
"description": "Country for the Veteran's new address. Value must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -1913,6 +1919,7 @@
"description": "International phone of point of contact.",
"type": "string",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -1947,12 +1954,14 @@
"type": "string",
"nullable": true,
"description": "Approximate begin date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
},
"endDate": {
"type": "string",
"nullable": true,
"description": "Approximate end date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
}
}
@@ -1978,6 +1987,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Other location(s) where Veteran served."
},
"serviceDates": {
@@ -2031,6 +2041,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Exposure to asbestos."
},
"exposureDates": {
@@ -2069,12 +2080,14 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Hazard the Veteran was exposed to."
},
"exposureLocation": {
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Location where the exposure happened."
},
"exposureDates": {
@@ -2126,6 +2139,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -2136,6 +2150,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury. If the disabilityActionType is 'NEW', the serviceRelevance is required.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"approximateDate": {
@@ -2198,6 +2213,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -2208,6 +2224,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"disabilityActionType": {
@@ -2340,6 +2357,7 @@
"serviceBranch": {
"description": "Branch of service during period. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"example": "Air Force"
},
"serviceComponent": {
@@ -2419,10 +2437,12 @@
"unitName": {
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"pattern": "^$|([a-zA-Z0-9\\-'.,# ][a-zA-Z0-9\\-'.,# ]?)*$"
},
"unitAddress": {
"type": "string",
+ "maxLength": 1000,
"pattern": "^$|^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
"nullable": true
},
@@ -2532,6 +2552,7 @@
"futureMilitaryRetiredPayExplanation": {
"description": "Explains why future pay will be received.",
"type": "string",
+ "maxLength": 1000,
"example": "Will be retiring soon.",
"nullable": true
},
@@ -2543,6 +2564,7 @@
"branchOfService": {
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"nullable": true,
"example": "Air Force"
},
@@ -2598,6 +2620,7 @@
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Air Force"
},
"preTaxAmountReceived": {
@@ -2885,6 +2908,7 @@
"serviceNumber": {
"type": "string",
"description": "Service identification number",
+ "maxLength": 1000,
"nullable": true
},
"veteranNumber": {
@@ -2905,6 +2929,7 @@
"type": "string",
"description": "Veteran's international phone number.",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -2947,6 +2972,7 @@
"description": "City for the Veteran's current mailing address.",
"type": "string",
"pattern": "^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -2958,6 +2984,7 @@
"country": {
"description": "Country for the Veteran's current mailing address. Must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -3043,6 +3070,7 @@
"description": "City for the Veteran's new address.",
"type": "string",
"pattern": "^$|^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -3054,6 +3082,7 @@
"country": {
"description": "Country for the Veteran's new address. Value must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -3173,6 +3202,7 @@
"description": "International phone of point of contact.",
"type": "string",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -3207,12 +3237,14 @@
"type": "string",
"nullable": true,
"description": "Approximate begin date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
},
"endDate": {
"type": "string",
"nullable": true,
"description": "Approximate end date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
}
}
@@ -3238,6 +3270,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Other location(s) where Veteran served."
},
"serviceDates": {
@@ -3291,6 +3324,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Exposure to asbestos."
},
"exposureDates": {
@@ -3329,12 +3363,14 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Hazard the Veteran was exposed to."
},
"exposureLocation": {
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Location where the exposure happened."
},
"exposureDates": {
@@ -3386,6 +3422,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -3396,6 +3433,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury. If the disabilityActionType is 'NEW', the serviceRelevance is required.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"approximateDate": {
@@ -3458,6 +3496,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -3468,6 +3507,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"disabilityActionType": {
@@ -3600,6 +3640,7 @@
"serviceBranch": {
"description": "Branch of service during period. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"example": "Air Force"
},
"serviceComponent": {
@@ -3679,10 +3720,12 @@
"unitName": {
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"pattern": "^$|([a-zA-Z0-9\\-'.,# ][a-zA-Z0-9\\-'.,# ]?)*$"
},
"unitAddress": {
"type": "string",
+ "maxLength": 1000,
"pattern": "^$|^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
"nullable": true
},
@@ -3792,6 +3835,7 @@
"futureMilitaryRetiredPayExplanation": {
"description": "Explains why future pay will be received.",
"type": "string",
+ "maxLength": 1000,
"example": "Will be retiring soon.",
"nullable": true
},
@@ -3803,6 +3847,7 @@
"branchOfService": {
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"nullable": true,
"example": "Air Force"
},
@@ -3858,6 +3903,7 @@
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Air Force"
},
"preTaxAmountReceived": {
@@ -4690,6 +4736,7 @@
"serviceNumber": {
"type": "string",
"description": "Service identification number",
+ "maxLength": 1000,
"nullable": true
},
"veteranNumber": {
@@ -4710,6 +4757,7 @@
"type": "string",
"description": "Veteran's international phone number.",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -4752,6 +4800,7 @@
"description": "City for the Veteran's current mailing address.",
"type": "string",
"pattern": "^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -4763,6 +4812,7 @@
"country": {
"description": "Country for the Veteran's current mailing address. Must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -4848,6 +4898,7 @@
"description": "City for the Veteran's new address.",
"type": "string",
"pattern": "^$|^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -4859,6 +4910,7 @@
"country": {
"description": "Country for the Veteran's new address. Value must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -4978,6 +5030,7 @@
"description": "International phone of point of contact.",
"type": "string",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -5012,12 +5065,14 @@
"type": "string",
"nullable": true,
"description": "Approximate begin date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
},
"endDate": {
"type": "string",
"nullable": true,
"description": "Approximate end date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
}
}
@@ -5043,6 +5098,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Other location(s) where Veteran served."
},
"serviceDates": {
@@ -5096,6 +5152,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Exposure to asbestos."
},
"exposureDates": {
@@ -5134,12 +5191,14 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Hazard the Veteran was exposed to."
},
"exposureLocation": {
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Location where the exposure happened."
},
"exposureDates": {
@@ -5191,6 +5250,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -5201,6 +5261,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury. If the disabilityActionType is 'NEW', the serviceRelevance is required.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"approximateDate": {
@@ -5263,6 +5324,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -5273,6 +5335,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"disabilityActionType": {
@@ -5405,6 +5468,7 @@
"serviceBranch": {
"description": "Branch of service during period. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"example": "Air Force"
},
"serviceComponent": {
@@ -5484,10 +5548,12 @@
"unitName": {
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"pattern": "^$|([a-zA-Z0-9\\-'.,# ][a-zA-Z0-9\\-'.,# ]?)*$"
},
"unitAddress": {
"type": "string",
+ "maxLength": 1000,
"pattern": "^$|^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
"nullable": true
},
@@ -5597,6 +5663,7 @@
"futureMilitaryRetiredPayExplanation": {
"description": "Explains why future pay will be received.",
"type": "string",
+ "maxLength": 1000,
"example": "Will be retiring soon.",
"nullable": true
},
@@ -5608,6 +5675,7 @@
"branchOfService": {
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"nullable": true,
"example": "Air Force"
},
@@ -5663,6 +5731,7 @@
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Air Force"
},
"preTaxAmountReceived": {
@@ -6003,7 +6072,7 @@
"application/json": {
"example": {
"data": {
- "id": "cf532e4e-e89e-4f9c-aebd-ce8361336a41",
+ "id": "6be9b240-267c-4c9c-b8d5-af1cd4068308",
"type": "forms/526",
"attributes": {
"veteran": {
@@ -8087,8 +8156,8 @@
"id": "1",
"type": "intent_to_file",
"attributes": {
- "creationDate": "2024-03-26",
- "expirationDate": "2025-03-26",
+ "creationDate": "2024-04-24",
+ "expirationDate": "2025-04-24",
"type": "compensation",
"status": "active"
}
@@ -8807,7 +8876,7 @@
"status": "422",
"detail": "Could not retrieve Power of Attorney due to multiple representatives with code: A1Q",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:112:in `representative'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:130:in `representative'"
}
}
]
@@ -8906,7 +8975,7 @@
"application/json": {
"example": {
"data": {
- "id": "29b16b36-3108-411f-9f5f-2c1c2e147ea3",
+ "id": "867b7baa-8dbe-4053-823f-788218fa6984",
"type": "individual",
"attributes": {
"code": "083",
@@ -9106,9 +9175,9 @@
{
"title": "Resource not found",
"status": "404",
- "detail": "Could not find an Accredited Representative with registration number: 67890 and poa code: 083",
+ "detail": "Could not find an Accredited Representative with registration number: 999999999999 and poa code: 083",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/individual_controller.rb:35:in `validate_individual_poa_code!'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:70:in `validate_registration_number!'"
}
}
]
@@ -9534,7 +9603,7 @@
},
"representative": {
"poaCode": "083",
- "registrationNumber": "67890",
+ "registrationNumber": "999999999999",
"type": "ATTORNEY",
"address": {
"addressLine1": "123",
@@ -9602,7 +9671,7 @@
"application/json": {
"example": {
"data": {
- "id": "a7114d11-8ffd-4545-ad99-d70e74991e11",
+ "id": "c54cfb3e-8ec8-48ce-bb19-52847bdd9bde",
"type": "organization",
"attributes": {
"code": "083",
@@ -9810,9 +9879,9 @@
{
"title": "Resource not found",
"status": "404",
- "detail": "Could not find an Accredited Representative with registration number: 67890 and poa code: 083",
+ "detail": "Could not find an Accredited Representative with registration number: 999999999999 and poa code: 083",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/organization_controller.rb:35:in `validate_org_poa_code!'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:70:in `validate_registration_number!'"
}
}
]
@@ -10180,7 +10249,7 @@
},
"serviceOrganization": {
"poaCode": "083",
- "registrationNumber": "67890"
+ "registrationNumber": "999999999999"
}
}
}
@@ -10429,9 +10498,9 @@
{
"title": "Resource not found",
"status": "404",
- "detail": "Could not find an Accredited Representative with registration number: 67890 and poa code: 083",
+ "detail": "Could not find an Accredited Representative with registration number: 999999999999 and poa code: 083",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/individual_controller.rb:35:in `validate_individual_poa_code!'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:70:in `validate_registration_number!'"
}
}
]
@@ -10857,7 +10926,7 @@
},
"representative": {
"poaCode": "083",
- "registrationNumber": "67890",
+ "registrationNumber": "999999999999",
"type": "ATTORNEY",
"address": {
"addressLine1": "123",
@@ -11124,9 +11193,9 @@
{
"title": "Resource not found",
"status": "404",
- "detail": "Could not find an Accredited Representative with registration number: 67890 and poa code: 083",
+ "detail": "Could not find an Accredited Representative with registration number: 999999999999 and poa code: 083",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/organization_controller.rb:35:in `validate_org_poa_code!'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:70:in `validate_registration_number!'"
}
}
]
@@ -11494,7 +11563,7 @@
},
"serviceOrganization": {
"poaCode": "083",
- "registrationNumber": "67890"
+ "registrationNumber": "999999999999"
}
}
}
@@ -11562,11 +11631,11 @@
"application/json": {
"example": {
"data": {
- "id": "7b0c58e1-4bf7-413c-a3ab-c8f6b95208b0",
+ "id": "af367b07-5484-4eb7-8a2b-3d4bf1ba447c",
"type": "claimsApiPowerOfAttorneys",
"attributes": {
"status": "submitted",
- "dateRequestAccepted": "2024-03-26",
+ "dateRequestAccepted": "2024-04-24",
"representative": {
"serviceOrganization": {
"poaCode": "074"
@@ -11802,4 +11871,4 @@
}
}
]
-}
+}
\ No newline at end of file
diff --git a/modules/claims_api/app/swagger/claims_api/v2/production/swagger.json b/modules/claims_api/app/swagger/claims_api/v2/production/swagger.json
index 64add52afd5..98196980051 100644
--- a/modules/claims_api/app/swagger/claims_api/v2/production/swagger.json
+++ b/modules/claims_api/app/swagger/claims_api/v2/production/swagger.json
@@ -684,7 +684,7 @@
"lighthouseId": null,
"maxEstClaimDate": null,
"minEstClaimDate": null,
- "status": "COMPLETE",
+ "status": "CANCELED",
"submitterApplicationCode": "EBN",
"submitterRoleCode": "VET",
"supportingDocuments": [
@@ -1342,6 +1342,7 @@
"serviceNumber": {
"type": "string",
"description": "Service identification number",
+ "maxLength": 1000,
"nullable": true
},
"veteranNumber": {
@@ -1362,6 +1363,7 @@
"type": "string",
"description": "Veteran's international phone number.",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -1404,6 +1406,7 @@
"description": "City for the Veteran's current mailing address.",
"type": "string",
"pattern": "^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -1415,6 +1418,7 @@
"country": {
"description": "Country for the Veteran's current mailing address. Must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -1500,6 +1504,7 @@
"description": "City for the Veteran's new address.",
"type": "string",
"pattern": "^$|^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -1511,6 +1516,7 @@
"country": {
"description": "Country for the Veteran's new address. Value must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -1630,6 +1636,7 @@
"description": "International phone of point of contact.",
"type": "string",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -1664,12 +1671,14 @@
"type": "string",
"nullable": true,
"description": "Approximate begin date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
},
"endDate": {
"type": "string",
"nullable": true,
"description": "Approximate end date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
}
}
@@ -1695,6 +1704,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Other location(s) where Veteran served."
},
"serviceDates": {
@@ -1748,6 +1758,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Exposure to asbestos."
},
"exposureDates": {
@@ -1786,12 +1797,14 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Hazard the Veteran was exposed to."
},
"exposureLocation": {
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Location where the exposure happened."
},
"exposureDates": {
@@ -1843,6 +1856,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -1853,6 +1867,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury. If the disabilityActionType is 'NEW', the serviceRelevance is required.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"approximateDate": {
@@ -1915,6 +1930,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -1925,6 +1941,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"disabilityActionType": {
@@ -2057,6 +2074,7 @@
"serviceBranch": {
"description": "Branch of service during period. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"example": "Air Force"
},
"serviceComponent": {
@@ -2136,10 +2154,12 @@
"unitName": {
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"pattern": "^$|([a-zA-Z0-9\\-'.,# ][a-zA-Z0-9\\-'.,# ]?)*$"
},
"unitAddress": {
"type": "string",
+ "maxLength": 1000,
"pattern": "^$|^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
"nullable": true
},
@@ -2249,6 +2269,7 @@
"futureMilitaryRetiredPayExplanation": {
"description": "Explains why future pay will be received.",
"type": "string",
+ "maxLength": 1000,
"example": "Will be retiring soon.",
"nullable": true
},
@@ -2260,6 +2281,7 @@
"branchOfService": {
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"nullable": true,
"example": "Air Force"
},
@@ -2315,6 +2337,7 @@
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Air Force"
},
"preTaxAmountReceived": {
@@ -2602,6 +2625,7 @@
"serviceNumber": {
"type": "string",
"description": "Service identification number",
+ "maxLength": 1000,
"nullable": true
},
"veteranNumber": {
@@ -2622,6 +2646,7 @@
"type": "string",
"description": "Veteran's international phone number.",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -2664,6 +2689,7 @@
"description": "City for the Veteran's current mailing address.",
"type": "string",
"pattern": "^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -2675,6 +2701,7 @@
"country": {
"description": "Country for the Veteran's current mailing address. Must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -2760,6 +2787,7 @@
"description": "City for the Veteran's new address.",
"type": "string",
"pattern": "^$|^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -2771,6 +2799,7 @@
"country": {
"description": "Country for the Veteran's new address. Value must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -2890,6 +2919,7 @@
"description": "International phone of point of contact.",
"type": "string",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -2924,12 +2954,14 @@
"type": "string",
"nullable": true,
"description": "Approximate begin date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
},
"endDate": {
"type": "string",
"nullable": true,
"description": "Approximate end date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
}
}
@@ -2955,6 +2987,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Other location(s) where Veteran served."
},
"serviceDates": {
@@ -3008,6 +3041,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Exposure to asbestos."
},
"exposureDates": {
@@ -3046,12 +3080,14 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Hazard the Veteran was exposed to."
},
"exposureLocation": {
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Location where the exposure happened."
},
"exposureDates": {
@@ -3103,6 +3139,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -3113,6 +3150,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury. If the disabilityActionType is 'NEW', the serviceRelevance is required.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"approximateDate": {
@@ -3175,6 +3213,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -3185,6 +3224,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"disabilityActionType": {
@@ -3317,6 +3357,7 @@
"serviceBranch": {
"description": "Branch of service during period. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"example": "Air Force"
},
"serviceComponent": {
@@ -3396,10 +3437,12 @@
"unitName": {
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"pattern": "^$|([a-zA-Z0-9\\-'.,# ][a-zA-Z0-9\\-'.,# ]?)*$"
},
"unitAddress": {
"type": "string",
+ "maxLength": 1000,
"pattern": "^$|^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
"nullable": true
},
@@ -3509,6 +3552,7 @@
"futureMilitaryRetiredPayExplanation": {
"description": "Explains why future pay will be received.",
"type": "string",
+ "maxLength": 1000,
"example": "Will be retiring soon.",
"nullable": true
},
@@ -3520,6 +3564,7 @@
"branchOfService": {
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"nullable": true,
"example": "Air Force"
},
@@ -3575,6 +3620,7 @@
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Air Force"
},
"preTaxAmountReceived": {
@@ -4407,6 +4453,7 @@
"serviceNumber": {
"type": "string",
"description": "Service identification number",
+ "maxLength": 1000,
"nullable": true
},
"veteranNumber": {
@@ -4427,6 +4474,7 @@
"type": "string",
"description": "Veteran's international phone number.",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -4469,6 +4517,7 @@
"description": "City for the Veteran's current mailing address.",
"type": "string",
"pattern": "^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -4480,6 +4529,7 @@
"country": {
"description": "Country for the Veteran's current mailing address. Must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -4565,6 +4615,7 @@
"description": "City for the Veteran's new address.",
"type": "string",
"pattern": "^$|^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -4576,6 +4627,7 @@
"country": {
"description": "Country for the Veteran's new address. Value must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -4695,6 +4747,7 @@
"description": "International phone of point of contact.",
"type": "string",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -4729,12 +4782,14 @@
"type": "string",
"nullable": true,
"description": "Approximate begin date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
},
"endDate": {
"type": "string",
"nullable": true,
"description": "Approximate end date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
}
}
@@ -4760,6 +4815,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Other location(s) where Veteran served."
},
"serviceDates": {
@@ -4813,6 +4869,7 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Exposure to asbestos."
},
"exposureDates": {
@@ -4851,12 +4908,14 @@
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Hazard the Veteran was exposed to."
},
"exposureLocation": {
"type": "string",
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Location where the exposure happened."
},
"exposureDates": {
@@ -4908,6 +4967,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -4918,6 +4978,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury. If the disabilityActionType is 'NEW', the serviceRelevance is required.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"approximateDate": {
@@ -4980,6 +5041,7 @@
"type": "string",
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": [
"Agent Orange",
"radiation",
@@ -4990,6 +5052,7 @@
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"disabilityActionType": {
@@ -5122,6 +5185,7 @@
"serviceBranch": {
"description": "Branch of service during period. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"example": "Air Force"
},
"serviceComponent": {
@@ -5201,10 +5265,12 @@
"unitName": {
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"pattern": "^$|([a-zA-Z0-9\\-'.,# ][a-zA-Z0-9\\-'.,# ]?)*$"
},
"unitAddress": {
"type": "string",
+ "maxLength": 1000,
"pattern": "^$|^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
"nullable": true
},
@@ -5314,6 +5380,7 @@
"futureMilitaryRetiredPayExplanation": {
"description": "Explains why future pay will be received.",
"type": "string",
+ "maxLength": 1000,
"example": "Will be retiring soon.",
"nullable": true
},
@@ -5325,6 +5392,7 @@
"branchOfService": {
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"nullable": true,
"example": "Air Force"
},
@@ -5380,6 +5448,7 @@
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
"nullable": true,
+ "maxLength": 1000,
"example": "Air Force"
},
"preTaxAmountReceived": {
@@ -5720,7 +5789,7 @@
"application/json": {
"example": {
"data": {
- "id": "8b3c6607-078b-419b-8549-726da40193df",
+ "id": "05d0b0a5-f2c6-40fb-a88a-7f8fb6888649",
"type": "forms/526",
"attributes": {
"veteran": {
@@ -7804,8 +7873,8 @@
"id": "1",
"type": "intent_to_file",
"attributes": {
- "creationDate": "2024-03-26",
- "expirationDate": "2025-03-26",
+ "creationDate": "2024-04-24",
+ "expirationDate": "2025-04-24",
"type": "compensation",
"status": "active"
}
@@ -8524,7 +8593,7 @@
"status": "422",
"detail": "Could not retrieve Power of Attorney due to multiple representatives with code: A1Q",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:112:in `representative'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:130:in `representative'"
}
}
]
@@ -8623,7 +8692,7 @@
"application/json": {
"example": {
"data": {
- "id": "9a9b6db5-abfc-45f3-ab60-785e3fb052ed",
+ "id": "6f744006-a5d4-4df8-8869-735a7a011c2b",
"type": "individual",
"attributes": {
"code": "083",
@@ -8823,9 +8892,9 @@
{
"title": "Resource not found",
"status": "404",
- "detail": "Could not find an Accredited Representative with registration number: 67890 and poa code: 083",
+ "detail": "Could not find an Accredited Representative with registration number: 999999999999 and poa code: 083",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/individual_controller.rb:35:in `validate_individual_poa_code!'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:70:in `validate_registration_number!'"
}
}
]
@@ -9251,7 +9320,7 @@
},
"representative": {
"poaCode": "083",
- "registrationNumber": "67890",
+ "registrationNumber": "999999999999",
"type": "ATTORNEY",
"address": {
"addressLine1": "123",
@@ -9319,7 +9388,7 @@
"application/json": {
"example": {
"data": {
- "id": "618d9ba4-44cf-490a-bd56-8012b59b30e7",
+ "id": "3a617b31-b98c-408a-844c-9bf3eef46b10",
"type": "organization",
"attributes": {
"code": "083",
@@ -9527,9 +9596,9 @@
{
"title": "Resource not found",
"status": "404",
- "detail": "Could not find an Accredited Representative with registration number: 67890 and poa code: 083",
+ "detail": "Could not find an Accredited Representative with registration number: 999999999999 and poa code: 083",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/organization_controller.rb:35:in `validate_org_poa_code!'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:70:in `validate_registration_number!'"
}
}
]
@@ -9897,7 +9966,7 @@
},
"serviceOrganization": {
"poaCode": "083",
- "registrationNumber": "67890"
+ "registrationNumber": "999999999999"
}
}
}
@@ -10146,9 +10215,9 @@
{
"title": "Resource not found",
"status": "404",
- "detail": "Could not find an Accredited Representative with registration number: 67890 and poa code: 083",
+ "detail": "Could not find an Accredited Representative with registration number: 999999999999 and poa code: 083",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/individual_controller.rb:35:in `validate_individual_poa_code!'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:70:in `validate_registration_number!'"
}
}
]
@@ -10574,7 +10643,7 @@
},
"representative": {
"poaCode": "083",
- "registrationNumber": "67890",
+ "registrationNumber": "999999999999",
"type": "ATTORNEY",
"address": {
"addressLine1": "123",
@@ -10841,9 +10910,9 @@
{
"title": "Resource not found",
"status": "404",
- "detail": "Could not find an Accredited Representative with registration number: 67890 and poa code: 083",
+ "detail": "Could not find an Accredited Representative with registration number: 999999999999 and poa code: 083",
"source": {
- "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/organization_controller.rb:35:in `validate_org_poa_code!'"
+ "pointer": "/modules/claims_api/app/controllers/claims_api/v2/veterans/power_of_attorney/base_controller.rb:70:in `validate_registration_number!'"
}
}
]
@@ -11211,7 +11280,7 @@
},
"serviceOrganization": {
"poaCode": "083",
- "registrationNumber": "67890"
+ "registrationNumber": "999999999999"
}
}
}
@@ -11279,11 +11348,11 @@
"application/json": {
"example": {
"data": {
- "id": "5d78a9f2-fffb-4867-a621-6ddee5bd5e58",
+ "id": "475c01f3-1705-4639-a793-7a80074884ea",
"type": "claimsApiPowerOfAttorneys",
"attributes": {
"status": "submitted",
- "dateRequestAccepted": "2024-03-26",
+ "dateRequestAccepted": "2024-04-24",
"representative": {
"serviceOrganization": {
"poaCode": "074"
@@ -11519,4 +11588,4 @@
}
}
]
-}
+}
\ No newline at end of file
diff --git a/modules/claims_api/config/schemas/v2/526.json b/modules/claims_api/config/schemas/v2/526.json
index c498373a404..fe5cc33d1bc 100644
--- a/modules/claims_api/config/schemas/v2/526.json
+++ b/modules/claims_api/config/schemas/v2/526.json
@@ -27,6 +27,7 @@
"serviceNumber": {
"type": ["null", "string"],
"description": "Service identification number",
+ "maxLength": 1000,
"nullable": true
},
"veteranNumber": {
@@ -47,6 +48,7 @@
"type": ["string", "null"],
"description": "Veteran's international phone number.",
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -89,6 +91,7 @@
"description": "City for the Veteran's current mailing address.",
"type": "string",
"pattern": "^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -100,6 +103,7 @@
"country": {
"description": "Country for the Veteran's current mailing address. Must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -182,6 +186,7 @@
"description": "City for the Veteran's new address.",
"type": "string",
"pattern": "^$|^([-a-zA-Z0-9'.#]([-a-zA-Z0-9'.# ])?)+$",
+ "maxLength": 1000,
"example": "Portland"
},
"state": {
@@ -193,6 +198,7 @@
"country": {
"description": "Country for the Veteran's new address. Value must match the values returned by the /countries endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current).",
"type": "string",
+ "maxLength": 1000,
"example": "USA"
},
"zipFirstFive": {
@@ -314,6 +320,7 @@
"description": "International phone of point of contact.",
"type": ["string", "null"],
"example": "+44 20 1234 5678",
+ "maxLength": 1000,
"nullable": true
}
}
@@ -345,12 +352,14 @@
"type": ["string", "null"],
"nullable": true,
"description": "Approximate begin date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
},
"endDate": {
"type": ["string", "null"],
"nullable": true,
"description": "Approximate end date for serving in Gulf War hazard location.",
+ "pattern": "^(?:19|20)[0-9][0-9]$|^(?:19|20)[0-9][0-9]-(0[1-9]|1[0-2])$",
"example": "2018-06 or 2018"
}
}
@@ -373,6 +382,7 @@
"type": ["string", "null"],
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Other location(s) where Veteran served."
},
"serviceDates": {
@@ -427,6 +437,7 @@
"type": ["string", "null"],
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 5000,
"description": "Exposure to asbestos."
},
"exposureDates": {
@@ -465,12 +476,14 @@
"type": ["string", "null"],
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Hazard the Veteran was exposed to."
},
"exposureLocation": {
"type": ["string", "null"],
"nullable": true,
"pattern": "^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
+ "maxLength": 1000,
"description": "Location where the exposure happened."
},
"exposureDates": {
@@ -519,12 +532,14 @@
"type": ["string", "null"],
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": ["Agent Orange", "radiation", "burn pits"]
},
"serviceRelevance": {
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury. If the disabilityActionType is 'NEW', the serviceRelevance is required.",
"type": ["string", "null"],
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"approximateDate": {
@@ -583,12 +598,14 @@
"type": ["string", "null"],
"description": "What caused the disability?",
"nullable": true,
+ "maxLength": 1000,
"examples": ["Agent Orange", "radiation", "burn pits"]
},
"serviceRelevance": {
"description": "Explanation of how the disability(ies) relates to the in-service event/exposure/injury.",
"type": ["string", "null"],
"nullable": true,
+ "maxLength": 1000,
"example": "Heavy equipment operator in service."
},
"disabilityActionType": {
@@ -705,6 +722,7 @@
"serviceBranch": {
"description": "Branch of service during period. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": "string",
+ "maxLength": 1000,
"example": "Air Force"
},
"serviceComponent": {
@@ -774,10 +792,12 @@
"unitName": {
"type": ["string", "null"],
"nullable": true,
+ "maxLength": 1000,
"pattern": "^$|([a-zA-Z0-9\\-'.,# ][a-zA-Z0-9\\-'.,# ]?)*$"
},
"unitAddress": {
"type": ["string", "null"],
+ "maxLength": 1000,
"pattern": "^$|^([-a-zA-Z0-9'.,]([-a-zA-Z0-9'., ])?)+$",
"nullable": true
},
@@ -878,6 +898,7 @@
"futureMilitaryRetiredPayExplanation": {
"description": "Explains why future pay will be received.",
"type": ["string", "null"],
+ "maxLength": 1000,
"example": "Will be retiring soon.",
"nullable": true
},
@@ -889,6 +910,7 @@
"branchOfService": {
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": ["string", "null"],
+ "maxLength": 1000,
"nullable": true,
"example": "Air Force"
},
@@ -942,6 +964,7 @@
"description": "Branch of service. The /service-branches endpoint on the [Benefits Reference Data API](https://developer.va.gov/explore/benefits/docs/benefits_reference_data?version=current) may be used to retrieve list of possible service branches.",
"type": ["string", "null"],
"nullable": true,
+ "maxLength": 1000,
"example": "Air Force"
},
"preTaxAmountReceived": {
diff --git a/modules/claims_api/lib/bd/bd.rb b/modules/claims_api/lib/bd/bd.rb
index a435e1bf067..dc72ecb6625 100644
--- a/modules/claims_api/lib/bd/bd.rb
+++ b/modules/claims_api/lib/bd/bd.rb
@@ -33,7 +33,7 @@ def search(claim_id, file_number)
# Upload document of mapped claim
#
# @return success or failure
- def upload(claim:, pdf_path:, doc_type: 'L122', file_number: nil)
+ def upload(claim:, pdf_path:, doc_type: 'L122', file_number: nil, original_filename: nil)
unless File.exist? pdf_path
ClaimsApi::Logger.log('benefits_documents', detail: "Error uploading doc to BD: #{pdf_path} doesn't exist",
claim_id: claim&.id)
@@ -41,7 +41,7 @@ def upload(claim:, pdf_path:, doc_type: 'L122', file_number: nil)
end
@multipart = true
- body = generate_upload_body(claim:, doc_type:, pdf_path:, file_number:)
+ body = generate_upload_body(claim:, doc_type:, pdf_path:, file_number:, original_filename:)
res = client.post('documents', body)&.body&.deep_symbolize_keys
request_id = res&.dig(:data, :requestId)
ClaimsApi::Logger.log(
@@ -62,10 +62,11 @@ def upload(claim:, pdf_path:, doc_type: 'L122', file_number: nil)
# Generate form body to upload a document
#
# @return {parameters, file}
- def generate_upload_body(claim:, doc_type:, pdf_path:, file_number: nil)
+ def generate_upload_body(claim:, doc_type:, pdf_path:, file_number: nil, original_filename: nil)
payload = {}
veteran_name = "#{claim.auth_headers['va_eauth_firstName']}_#{claim.auth_headers['va_eauth_lastName']}"
- file_name = "526EZ_#{veteran_name}_#{claim.evss_id}.pdf"
+ file_name = generate_file_name(doc_type:, veteran_name:, claim_id: claim.evss_id, original_filename:)
+
data = {
data: {
systemName: 'VA.gov',
@@ -83,6 +84,25 @@ def generate_upload_body(claim:, doc_type:, pdf_path:, file_number: nil)
payload
end
+ def generate_file_name(doc_type:, veteran_name:, claim_id:, original_filename:)
+ if doc_type == 'L122'
+ "#{veteran_name}_#{claim_id}_526EZ.pdf"
+ else
+ filename = get_original_supporting_doc_file_name(original_filename)
+ "#{veteran_name}_#{claim_id}_#{filename}.pdf"
+ end
+ end
+
+ ##
+ # DisabilityCompensationDocuments method create_unique_filename adds a random 11 digit
+ # hex string to the original filename, so we remove that to yield the user-submitted
+ # filename to use as part of the filename uploaded to the BD service.
+ def get_original_supporting_doc_file_name(original_filename)
+ file_extension = File.extname(original_filename)
+ base_filename = File.basename(original_filename, file_extension)
+ base_filename[0...-12]
+ end
+
##
# Configure Faraday base class (and do auth)
#
diff --git a/modules/claims_api/lib/bgs_service/veteran_representative_service.rb b/modules/claims_api/lib/bgs_service/veteran_representative_service.rb
index 7b798d89e24..2ef438d9482 100644
--- a/modules/claims_api/lib/bgs_service/veteran_representative_service.rb
+++ b/modules/claims_api/lib/bgs_service/veteran_representative_service.rb
@@ -1,15 +1,16 @@
# frozen_string_literal: true
+require_relative 'veteran_representative_service/create_veteran_representative_request'
require_relative 'veteran_representative_service/read_all_veteran_representatives'
module ClaimsApi
class VeteranRepresentativeService < ClaimsApi::LocalBGS
private
- def make_request(**args)
+ def make_request(namespace:, **args)
super(
endpoint: 'VDC/VeteranRepresentativeService',
- namespaces: { 'ns0' => '/data' },
+ namespaces: { namespace => '/data' },
transform_response: false,
**args
)
diff --git a/modules/claims_api/lib/bgs_service/veteran_representative_service/create_veteran_representative_request.rb b/modules/claims_api/lib/bgs_service/veteran_representative_service/create_veteran_representative_request.rb
new file mode 100644
index 00000000000..69823f7f0c7
--- /dev/null
+++ b/modules/claims_api/lib/bgs_service/veteran_representative_service/create_veteran_representative_request.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module ClaimsApi
+ class VeteranRepresentativeService < ClaimsApi::LocalBGS
+ def create_veteran_representative(options)
+ injected = convert_nil_values(options)
+ body = Nokogiri::XML::DocumentFragment.parse <<~EOXML
+
+ #{injected}
+
+ EOXML
+
+ make_request(
+ namespace: 'data',
+ action: 'createVeteranRepresentative',
+ body: body.to_s,
+ key: 'VeteranRepresentativeReturn'
+ )
+ end
+ end
+end
diff --git a/modules/claims_api/lib/bgs_service/veteran_representative_service/read_all_veteran_representatives.rb b/modules/claims_api/lib/bgs_service/veteran_representative_service/read_all_veteran_representatives.rb
index b9de1f6f373..9dfeb0e3c69 100644
--- a/modules/claims_api/lib/bgs_service/veteran_representative_service/read_all_veteran_representatives.rb
+++ b/modules/claims_api/lib/bgs_service/veteran_representative_service/read_all_veteran_representatives.rb
@@ -13,7 +13,7 @@ def read_all_veteran_representatives(type_code:, ptcpnt_id:)
#{type_code}
EOXML
- ret = make_request(action: 'readAllVeteranRepresentatives', body:)
+ ret = make_request(namespace: 'ns0', action: 'readAllVeteranRepresentatives', body:)
&.dig('VeteranRepresentativeReturnList') || []
[ret].flatten
end
diff --git a/modules/claims_api/spec/fixtures/test_client.p12 b/modules/claims_api/spec/fixtures/test_client.p12
index 48fde3d8efa..b0e862698e9 100644
Binary files a/modules/claims_api/spec/fixtures/test_client.p12 and b/modules/claims_api/spec/fixtures/test_client.p12 differ
diff --git a/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122/invalid_poa.json b/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122/invalid_poa.json
index c8e51c69b95..57ef9056d29 100644
--- a/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122/invalid_poa.json
+++ b/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122/invalid_poa.json
@@ -12,7 +12,7 @@
},
"serviceOrganization": {
"poaCode": "aaa",
- "registrationNumber": "67890"
+ "registrationNumber": "999999999999"
}
}
}
diff --git a/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122/valid.json b/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122/valid.json
index 82a23c3051b..fe439564f1a 100644
--- a/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122/valid.json
+++ b/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122/valid.json
@@ -12,7 +12,7 @@
},
"serviceOrganization": {
"poaCode": "083",
- "registrationNumber": "67890"
+ "registrationNumber": "999999999999"
}
}
}
diff --git a/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122a/invalid_poa.json b/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122a/invalid_poa.json
index a93b72d9101..fd18c06f7f4 100644
--- a/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122a/invalid_poa.json
+++ b/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122a/invalid_poa.json
@@ -12,7 +12,7 @@
},
"representative": {
"poaCode": "aaa",
- "registrationNumber": "67890",
+ "registrationNumber": "999999999999",
"type": "ATTORNEY",
"address": {
"addressLine1": "123",
diff --git a/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122a/valid.json b/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122a/valid.json
index ce086b08903..ed6315f06bc 100644
--- a/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122a/valid.json
+++ b/modules/claims_api/spec/fixtures/v2/veterans/power_of_attorney/2122a/valid.json
@@ -14,7 +14,7 @@
},
"representative": {
"poaCode": "083",
- "registrationNumber": "67890",
+ "registrationNumber": "999999999999",
"type": "ATTORNEY",
"address": {
"addressLine1": "123",
diff --git a/modules/claims_api/spec/lib/claims_api/bd_spec.rb b/modules/claims_api/spec/lib/claims_api/bd_spec.rb
index 67b2cb70d8c..33fa48aaf72 100644
--- a/modules/claims_api/spec/lib/claims_api/bd_spec.rb
+++ b/modules/claims_api/spec/lib/claims_api/bd_spec.rb
@@ -24,7 +24,8 @@
end
it 'uploads an attachment to BD' do
- result = subject.send(:generate_upload_body, claim:, doc_type: 'L023', pdf_path:)
+ result = subject.send(:generate_upload_body, claim:, doc_type: 'L023', original_filename: '21-526EZ.pdf',
+ pdf_path:)
js = JSON.parse(result[:parameters].read)
expect(js['data']['docType']).to eq 'L023'
end
diff --git a/modules/claims_api/spec/lib/claims_api/bgs/veteran_representative_service/create_veteran_representative_request_spec.rb b/modules/claims_api/spec/lib/claims_api/bgs/veteran_representative_service/create_veteran_representative_request_spec.rb
new file mode 100644
index 00000000000..ebcf7905201
--- /dev/null
+++ b/modules/claims_api/spec/lib/claims_api/bgs/veteran_representative_service/create_veteran_representative_request_spec.rb
@@ -0,0 +1,147 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'bgs_service/veteran_representative_service'
+require Rails.root.join('modules', 'claims_api', 'spec', 'support', 'bgs_client_helpers.rb')
+
+metadata = {
+ bgs: {
+ service: 'veteran_representative_service',
+ operation: 'create_veteran_representative'
+ }
+}
+
+describe ClaimsApi::VeteranRepresentativeService, metadata do
+ describe '#create_veteran_representative' do
+ subject do
+ service = described_class.new(**header_params)
+ service.create_veteran_representative(**params)
+ end
+
+ let(:header_params) do
+ {
+ external_uid: 'keyHere',
+ external_key: 'keyHere'
+ }
+ end
+
+ describe 'with valid request params' do
+ let(:params) do
+ {
+ form_type_code: '21-22',
+ proc_id: '3854909',
+ veteran_ptcpnt_id: '182359',
+ poa_code: '074',
+ section_7332_auth: false,
+ limitation_drug_abuse: false,
+ limitation_alcohol: false,
+ limitation_hiv: false,
+ limitation_s_c_a: false,
+ limitation_h_i_v: false,
+ change_address_auth: true,
+ vdc_status: 'Submitted',
+ representative_type: 'Recognized Veterans Service Organization',
+ claimant_ptcpnt_id: '182358',
+ # rubocop:disable Naming/VariableNumber
+ address_line_1: '76 Crowther Ave',
+ # rubocop:enable Naming/VariableNumber
+ city: 'Bridgeport',
+ postal_code: '06605',
+ state: 'CT',
+ submitted_date: '2024-04-22T19:27:37Z'
+ }
+ end
+
+ let(:expected_response) do
+ {
+ 'addressLine1' => '76 Crowther Ave',
+ 'addressLine2' => nil,
+ 'addressLine3' => nil,
+ 'changeAddressAuth' => 'true',
+ 'city' => 'Bridgeport',
+ 'claimantPtcpntId' => '182358',
+ 'claimantRelationship' => nil,
+ 'formTypeCode' => '21-22',
+ 'insuranceNumbers' => nil,
+ 'limitationAlcohol' => 'false',
+ 'limitationDrugAbuse' => 'false',
+ 'limitationHIV' => 'false',
+ 'limitationSCA' => 'false',
+ 'organizationName' => nil,
+ 'otherServiceBranch' => nil,
+ 'phoneNumber' => nil,
+ 'poaCode' => '074',
+ 'postalCode' => '06605',
+ 'procId' => '3854909',
+ 'representativeFirstName' => nil,
+ 'representativeLastName' => nil,
+ 'representativeLawFirmOrAgencyName' => nil,
+ 'representativeTitle' => nil,
+ 'representativeType' => 'Recognized Veterans Service Organization',
+ 'section7332Auth' => 'false',
+ 'serviceBranch' => nil,
+ 'serviceNumber' => nil,
+ 'state' => 'CT',
+ 'vdcStatus' => 'Submitted',
+ 'veteranPtcpntId' => '182359',
+ 'acceptedBy' => nil,
+ 'claimantFirstName' => 'VERNON',
+ 'claimantLastName' => 'WAGNER',
+ 'claimantMiddleName' => nil,
+ 'declinedBy' => nil,
+ 'declinedReason' => nil,
+ 'secondaryStatus' => nil,
+ 'veteranFirstName' => 'VERNON',
+ 'veteranLastName' => 'WAGNER',
+ 'veteranMiddleName' => nil,
+ 'veteranSSN' => nil,
+ 'veteranVAFileNumber' => nil
+ }
+ end
+
+ it 'returns a response with expected body' do
+ use_bgs_cassette('valid_params') do
+ expect(subject).to eq(expected_response)
+ end
+ end
+ end
+
+ describe 'with invalid params' do
+ describe 'with the MPI participant ID being used instead of the VNP participant ID' do
+ let(:params) do
+ {
+ form_type_code: '21-22',
+ proc_id: '3854909',
+ veteran_ptcpnt_id: '600043284',
+ poa_code: '074',
+ section_7332_auth: false,
+ limitation_drug_abuse: false,
+ limitation_alcohol: false,
+ limitation_hiv: false,
+ limitation_s_c_a: false,
+ limitation_h_i_v: false,
+ change_address_auth: true,
+ vdc_status: 'Submitted',
+ representative_type: 'Recognized Veterans Service Organization',
+ claimant_ptcpnt_id: '182358',
+ # rubocop:disable Naming/VariableNumber
+ address_line_1: '76 Crowther Ave',
+ # rubocop:enable Naming/VariableNumber
+ city: 'Bridgeport',
+ postal_code: '06605',
+ state: 'CT',
+ submitted_date: '2024-04-22T19:27:37Z'
+ }
+ end
+
+ it 'raises Common::Exceptions::ServiceError' do
+ use_bgs_cassette('mpi_ptcpnt_id_instead_of_vnp_ptcpnt_id') do
+ expect { subject }.to raise_error(
+ Common::Exceptions::ServiceError
+ )
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/modules/claims_api/spec/lib/claims_api/bgs/veteran_representative_service/veteran_representative_service_spec.rb b/modules/claims_api/spec/lib/claims_api/bgs/veteran_representative_service/veteran_representative_service_spec.rb
new file mode 100644
index 00000000000..c2db3c02fd1
--- /dev/null
+++ b/modules/claims_api/spec/lib/claims_api/bgs/veteran_representative_service/veteran_representative_service_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+require 'bgs_service/veteran_representative_service'
+require Rails.root.join('modules', 'claims_api', 'spec', 'support', 'bgs_client_helpers.rb')
+
+describe ClaimsApi::VeteranRepresentativeService do
+ let(:header_params) do
+ {
+ external_uid: 'xUid',
+ external_key: 'xKey'
+ }
+ end
+
+ describe 'with a namespace param' do
+ it 'does not raise ArgumentError' do
+ service = described_class.new(**header_params)
+ expect do
+ service.send(:make_request, namespace: 'testspace', action: 'testAction', body: 'this is the body',
+ key: 'ThisIsTheKey')
+ end.not_to raise_error(ArgumentError)
+ end
+ end
+
+ describe 'without the namespace param' do
+ let(:params) { { ptcpnt_id: '123456' } }
+
+ it 'raises ArgumentError' do
+ service = described_class.new(**header_params)
+ expect do
+ service.send(:make_request, action: 'testAction', body: 'this is the body',
+ key: 'ThisIsTheKey')
+ end.to raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/modules/claims_api/spec/requests/v2/veterans/power_of_attorney_ind_request_spec.rb b/modules/claims_api/spec/requests/v2/veterans/power_of_attorney_ind_request_spec.rb
index dee3b666e60..92689e629e2 100644
--- a/modules/claims_api/spec/requests/v2/veterans/power_of_attorney_ind_request_spec.rb
+++ b/modules/claims_api/spec/requests/v2/veterans/power_of_attorney_ind_request_spec.rb
@@ -19,7 +19,7 @@
before do
Veteran::Service::Representative.create!(representative_id: '12345', poa_codes: [individual_poa_code],
first_name: 'Abraham', last_name: 'Lincoln')
- Veteran::Service::Representative.create!(representative_id: '67890', poa_codes: [organization_poa_code],
+ Veteran::Service::Representative.create!(representative_id: '999999999999', poa_codes: [organization_poa_code],
first_name: 'George', last_name: 'Washington')
end
@@ -346,7 +346,7 @@
it 'returns a meaningful 404' do
mock_ccg(%w[claim.write claim.read]) do |auth_header|
- detail = 'Could not find an Accredited Representative with registration number: 67890 ' \
+ detail = 'Could not find an Accredited Representative with registration number: 999999999999 ' \
'and poa code: aaa'
post validate2122a_path, params: request_body, headers: auth_header
diff --git a/modules/claims_api/spec/requests/v2/veterans/power_of_attorney_org_request_spec.rb b/modules/claims_api/spec/requests/v2/veterans/power_of_attorney_org_request_spec.rb
index e9016bdde23..1e31d3f757c 100644
--- a/modules/claims_api/spec/requests/v2/veterans/power_of_attorney_org_request_spec.rb
+++ b/modules/claims_api/spec/requests/v2/veterans/power_of_attorney_org_request_spec.rb
@@ -17,7 +17,8 @@
describe 'PowerOfAttorney' do
before do
- Veteran::Service::Representative.create!(representative_id: '67890', poa_codes: [organization_poa_code],
+ Veteran::Service::Representative.create!(representative_id: '999999999999',
+ poa_codes: [organization_poa_code],
first_name: 'George', last_name: 'Washington')
Veteran::Service::Organization.create!(poa: organization_poa_code,
name: "#{organization_poa_code} - DISABLED AMERICAN VETERANS")
@@ -39,7 +40,7 @@
},
serviceOrganization: {
poaCode: organization_poa_code.to_s,
- registrationNumber: '67890'
+ registrationNumber: '999999999999'
}
}
}
@@ -103,7 +104,8 @@
context 'multiple reps with same poa code and registration number' do
let(:rep_id) do
- Veteran::Service::Representative.create!(representative_id: '67890', poa_codes: [organization_poa_code],
+ Veteran::Service::Representative.create!(representative_id: '999999999999',
+ poa_codes: [organization_poa_code],
first_name: 'George', last_name: 'Washington-test').id
end
@@ -181,7 +183,7 @@
it 'returns a meaningful 404' do
mock_ccg(%w[claim.write claim.read]) do |auth_header|
- detail = 'Could not find an Accredited Representative with registration number: 67890 ' \
+ detail = 'Could not find an Accredited Representative with registration number: 999999999999 ' \
'and poa code: aaa'
post validate2122_path, params: request_body, headers: auth_header
diff --git a/modules/claims_api/spec/requests/v2/veterans/rswag_power_of_attorney_spec.rb b/modules/claims_api/spec/requests/v2/veterans/rswag_power_of_attorney_spec.rb
index 9c17a58ad68..7158c3a3e56 100644
--- a/modules/claims_api/spec/requests/v2/veterans/rswag_power_of_attorney_spec.rb
+++ b/modules/claims_api/spec/requests/v2/veterans/rswag_power_of_attorney_spec.rb
@@ -184,7 +184,7 @@
expect_any_instance_of(local_bgs).to receive(:find_poa_by_participant_id).and_return(bgs_poa)
allow_any_instance_of(local_bgs).to receive(:find_poa_history_by_ptcpnt_id)
.and_return({ person_poa_history: nil })
- Veteran::Service::Representative.new(representative_id: '67890',
+ Veteran::Service::Representative.new(representative_id: '999999999999',
poa_codes: [poa_code],
first_name: 'Firstname',
last_name: 'Lastname',
@@ -352,7 +352,8 @@
Veteran::Service::Organization.create!(poa: organization_poa_code,
name: "#{organization_poa_code} - DISABLED AMERICAN VETERANS",
phone: '555-555-5555')
- Veteran::Service::Representative.create!(representative_id: '67890', poa_codes: [organization_poa_code],
+ Veteran::Service::Representative.create!(representative_id: '999999999999',
+ poa_codes: [organization_poa_code],
first_name: 'Firstname', last_name: 'Lastname',
phone: '555-555-5555')
@@ -510,7 +511,7 @@
end
before do |example|
- Veteran::Service::Representative.new(representative_id: '67890',
+ Veteran::Service::Representative.new(representative_id: '999999999999',
poa_codes: [poa_code],
first_name: 'Firstname',
last_name: 'Lastname',
@@ -679,7 +680,7 @@
before do |example|
Veteran::Service::Organization.create!(poa: poa_code)
- Veteran::Service::Representative.create!(representative_id: '67890', poa_codes: [poa_code],
+ Veteran::Service::Representative.create!(representative_id: '999999999999', poa_codes: [poa_code],
first_name: 'Firstname', last_name: 'Lastname',
phone: '555-555-5555')
diff --git a/modules/claims_api/spec/sidekiq/claim_uploader_spec.rb b/modules/claims_api/spec/sidekiq/claim_uploader_spec.rb
index 099cfb01737..0c2b94d2ef9 100644
--- a/modules/claims_api/spec/sidekiq/claim_uploader_spec.rb
+++ b/modules/claims_api/spec/sidekiq/claim_uploader_spec.rb
@@ -56,6 +56,8 @@
claim
end
+ let(:original_filename) { 'extras' }
+
it 'submits successfully' do
expect do
subject.perform_async(supporting_document.id)
@@ -134,7 +136,7 @@
allow(Tempfile).to receive(:new).and_return tf
allow(Flipper).to receive(:enabled?).with(:claims_claim_uploader_use_bd).and_return true
- args = { claim: auto_claim, doc_type: 'L122', pdf_path: tf.path }
+ args = { claim: auto_claim, doc_type: 'L122', original_filename: 'extras.pdf', pdf_path: tf.path }
expect_any_instance_of(ClaimsApi::BD).to receive(:upload).with(args).and_return true
subject.new.perform(auto_claim.id)
end
@@ -144,7 +146,8 @@
allow(Tempfile).to receive(:new).and_return tf
allow(Flipper).to receive(:enabled?).with(:claims_claim_uploader_use_bd).and_return true
- args = { claim: supporting_document.auto_established_claim, doc_type: 'L023', pdf_path: tf.path }
+ args = { claim: supporting_document.auto_established_claim, doc_type: 'L023',
+ original_filename: 'extras.pdf', pdf_path: tf.path }
expect_any_instance_of(ClaimsApi::BD).to receive(:upload).with(args).and_return true
subject.new.perform(supporting_document.id)
end
@@ -161,7 +164,8 @@
text: 'Error calling external service to upload claim document.' }
]
}
- args = { claim: supporting_document.auto_established_claim, doc_type: 'L023', pdf_path: tf.path }
+ args = { claim: supporting_document.auto_established_claim, doc_type: 'L023',
+ original_filename: 'extras.pdf', pdf_path: tf.path }
allow_any_instance_of(ClaimsApi::BD).to(
receive(:upload).with(args).and_raise(Common::Exceptions::BackendServiceException.new(
'', {}, 500, body
diff --git a/modules/debts_api/app/controllers/debts_api/v0/financial_status_reports_controller.rb b/modules/debts_api/app/controllers/debts_api/v0/financial_status_reports_controller.rb
index 76ec33c8869..1cff11148e6 100644
--- a/modules/debts_api/app/controllers/debts_api/v0/financial_status_reports_controller.rb
+++ b/modules/debts_api/app/controllers/debts_api/v0/financial_status_reports_controller.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'debts_api/v0/financial_status_report_service'
+require 'debts_api/v0/fsr_rehydration_service'
module DebtsApi
module V0
@@ -23,6 +24,27 @@ def download_pdf
)
end
+ def submissions
+ submissions = DebtsApi::V0::Form5655Submission.where(user_uuid: current_user.uuid)
+ render json: { 'submissions' => submissions.map { |sub| { 'id' => sub.id } } }
+ end
+
+ def rehydrate
+ submission_id = params[:submission_id]
+
+ DebtsApi::V0::FsrRehydrationService.attempt_rehydration(user_uuid: current_user.uuid, submission_id:)
+
+ render json: { result: 'FSR rehydrated' }
+ rescue ActiveRecord::RecordNotFound
+ render json: { error: "Form5655Submission record #{submission_id} not found." }, status: :not_found
+ rescue DebtsApi::V0::FsrRehydrationService::UserDoesNotOwnsubmission
+ render json: { error: "User #{current_user.uuid} does not own submission #{submission_id}" },
+ status: :unauthorized
+ rescue DebtsApi::V0::FsrRehydrationService::NoInProgressFormDataStored
+ render json: { error: "Form5655Submission record #{submission_id} missing InProgressForm data",
+ status: :not_found }
+ end
+
private
def render_not_found
diff --git a/modules/debts_api/config/routes.rb b/modules/debts_api/config/routes.rb
index 6b3ab5c1b7a..5fbb494ba96 100644
--- a/modules/debts_api/config/routes.rb
+++ b/modules/debts_api/config/routes.rb
@@ -5,9 +5,12 @@
resources :financial_status_reports, only: %i[create] do
collection do
get :download_pdf
+ get :submissions
end
end
+ get 'financial_status_reports/rehydrate_submission/:submission_id', to: 'financial_status_reports#rehydrate'
+
post 'calculate_total_assets', to: 'financial_status_reports_calculations#total_assets'
post 'calculate_monthly_expenses', to: 'financial_status_reports_calculations#monthly_expenses'
post 'calculate_all_expenses', to: 'financial_status_reports_calculations#all_expenses'
diff --git a/modules/debts_api/lib/debts_api/v0/fsr_rehydration_service.rb b/modules/debts_api/lib/debts_api/v0/fsr_rehydration_service.rb
new file mode 100644
index 00000000000..c66130b30b5
--- /dev/null
+++ b/modules/debts_api/lib/debts_api/v0/fsr_rehydration_service.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module DebtsApi
+ class V0::FsrRehydrationService
+ include SentryLogging
+
+ class UserDoesNotOwnsubmission < StandardError; end
+ class NoInProgressFormDataStored < StandardError; end
+
+ def self.attempt_rehydration(user_uuid:, submission_id:)
+ submission = DebtsApi::V0::Form5655Submission.find(submission_id)
+
+ raise NoInProgressFormDataStored unless submission.ipf_data
+ raise UserDoesNotOwnsubmission unless submission.user_uuid == user_uuid
+
+ submission.upsert_in_progress_form
+ end
+ end
+end
diff --git a/modules/debts_api/spec/request/debts_api/v0/financial_status_reports_controller_spec.rb b/modules/debts_api/spec/request/debts_api/v0/financial_status_reports_controller_spec.rb
index 63be330783b..35f7955f963 100644
--- a/modules/debts_api/spec/request/debts_api/v0/financial_status_reports_controller_spec.rb
+++ b/modules/debts_api/spec/request/debts_api/v0/financial_status_reports_controller_spec.rb
@@ -59,4 +59,39 @@ def mock_pdf_fill
expect(response.body).to eq(content)
end
end
+
+ describe '#rehydrate' do
+ context 'on a nonexistent submission' do
+ it 'renders a 404' do
+ get '/debts_api/v0/financial_status_reports/rehydrate_submission/1'
+ expect(response).to have_http_status(:not_found)
+ end
+ end
+
+ context 'on a submission you don\'t own' do
+ let(:form5655_submission) { create(:debts_api_form5655_submission) }
+
+ it 'renders a 404' do
+ form5655_submission
+ form5655_submission.update!(user_uuid: 'nottherightguy', ipf_data: '{"its":"me"}')
+ get "/debts_api/v0/financial_status_reports/rehydrate_submission/#{form5655_submission.id}"
+ expect(response.code).to eq('401')
+ body = "{\"error\":\"User #{user.uuid} does not own submission #{form5655_submission.id}\"}"
+ expect(response.body).to eq(body)
+ end
+ end
+
+ context 'on a submission you do own' do
+ let(:form5655_submission) do
+ create(:debts_api_form5655_submission, user_uuid: 'b2fab2b56af045e1a9e2394347af91ef')
+ end
+
+ it 'rehydrates In Progress Form' do
+ form5655_submission
+ form5655_submission.update!(user_uuid: user.uuid, ipf_data: '{"its":"me"}')
+ get "/debts_api/v0/financial_status_reports/rehydrate_submission/#{form5655_submission.id}"
+ expect(response.code).to eq('200')
+ end
+ end
+ end
end
diff --git a/modules/mobile/app/controllers/mobile/v0/appointments_controller.rb b/modules/mobile/app/controllers/mobile/v0/appointments_controller.rb
index 6525148a734..adff7bb4ea5 100644
--- a/modules/mobile/app/controllers/mobile/v0/appointments_controller.rb
+++ b/modules/mobile/app/controllers/mobile/v0/appointments_controller.rb
@@ -87,7 +87,7 @@ def fetch_appointments
# The mobile app does not distinguish between VA and CC errors so we are only indicating that there are errors
# If we ever want to distinguish be VA and CC errors, it will require coordination with the front-end team
def partial_errors(failures)
- if failures.present?
+ if appointment_errors?(failures)
{
errors: [{ source: 'VA Service' }]
}
@@ -95,12 +95,11 @@ def partial_errors(failures)
end
def get_response_status(failures)
- case failures&.size
- when 0, nil
- :ok
- else
- :multi_status
- end
+ appointment_errors?(failures) ? :multi_status : :ok
+ end
+
+ def appointment_errors?(failures)
+ failures.any? { |failure| failure[:appointment_errors].present? }
end
def filter_by_date_range(appointments)
diff --git a/modules/mobile/app/services/mobile/v2/appointments/provider_names.rb b/modules/mobile/app/services/mobile/v2/appointments/provider_names.rb
index 1f7473ecc86..4ec4528201d 100644
--- a/modules/mobile/app/services/mobile/v2/appointments/provider_names.rb
+++ b/modules/mobile/app/services/mobile/v2/appointments/provider_names.rb
@@ -20,10 +20,17 @@ def form_names_from_appointment_practitioners_list(practitioners_list)
return nil if practitioners_list.blank?
provider_names = []
+ missing_providers = []
practitioners_list.each do |practitioner|
- provider_names << find_provider_name(practitioner)
+ name, id = find_provider_name(practitioner)
+ if name
+ provider_names << name
+ else
+ missing_providers << id
+ end
end
- provider_names.compact.join(', ').presence
+ provider_names = provider_names.compact.join(', ').presence
+ [provider_names, missing_providers]
end
private
@@ -41,7 +48,7 @@ def find_provider_name(practitioner)
name = provider_data&.name&.strip&.presence
# cache even if it's nil to avoid duplicate requests
@providers_cache[id] = name
- name
+ [name, id]
end
def find_practitioner_name_in_list(practitioner)
diff --git a/modules/mobile/app/services/mobile/v2/appointments/proxy.rb b/modules/mobile/app/services/mobile/v2/appointments/proxy.rb
index 40348c892be..4fa4ed8ee02 100644
--- a/modules/mobile/app/services/mobile/v2/appointments/proxy.rb
+++ b/modules/mobile/app/services/mobile/v2/appointments/proxy.rb
@@ -24,13 +24,21 @@ def get_appointments(start_date:, end_date:, include_pending:, pagination_params
filterer = PresentationFilter.new(include_pending:)
appointments = appointments.keep_if { |appt| filterer.user_facing?(appt) }
- appointments = merge_clinic_facility_address(appointments)
- appointments = merge_auxiliary_clinic_info(appointments)
- appointments = merge_provider_names(appointments)
+ appointments, missing_facilities = merge_clinic_facility_address(appointments)
+ appointments, missing_clinics = merge_auxiliary_clinic_info(appointments)
+ appointments, missing_providers = merge_provider_names(appointments)
appointments = vaos_v2_to_v0_appointment_adapter.parse(appointments)
-
- [appointments.sort_by(&:start_date_utc), response[:meta][:failures]]
+ failures = [
+ { appointment_errors: Array.wrap(response[:meta][:failures]) },
+ { missing_facilities: },
+ { missing_clinics: },
+ { missing_providers: }
+ ]
+ failures.reject! { |failure| failure.values.first&.empty? }
+ Rails.logger.info('Mobile Appointment Partial Error', errors: failures) if failures.any?
+
+ [appointments.sort_by(&:start_date_utc), failures]
end
private
@@ -43,12 +51,18 @@ def merge_clinic_facility_address(appointments)
cached_facilities[facility_id] = appointments_helper.get_facility(facility_id)
end
+ missing_facilities = []
+
appointments.each do |appt|
facility_id = appt[:location_id]
next unless facility_id
appt[:location] = cached_facilities[facility_id]
+
+ missing_facilities << facility_id unless cached_facilities[facility_id]
end
+
+ [appointments, missing_facilities]
end
def merge_auxiliary_clinic_info(appointments)
@@ -59,6 +73,8 @@ def merge_auxiliary_clinic_info(appointments)
cached_clinics[clinic_id] = appointments_helper.get_clinic(location_id, clinic_id)
end
+ missing_clinics = []
+
appointments.each do |appt|
clinic_id = appt[:clinic]
next unless clinic_id
@@ -68,16 +84,26 @@ def merge_auxiliary_clinic_info(appointments)
physical_location = cached_clinics.dig(clinic_id, :physical_location)
appt[:physical_location] = physical_location
+
+ missing_clinics << clinic_id unless cached_clinics[clinic_id]
end
+ [appointments, missing_clinics]
end
def merge_provider_names(appointments)
provider_names_proxy = ProviderNames.new(@user)
+ missing_providers = []
appointments.each do |appt|
practitioners_list = appt[:practitioners]
- names = provider_names_proxy.form_names_from_appointment_practitioners_list(practitioners_list)
+ next unless practitioners_list
+
+ names, appointment_missing_providers =
+ provider_names_proxy.form_names_from_appointment_practitioners_list(practitioners_list)
appt[:healthcare_provider] = names
+ missing_providers.concat(appointment_missing_providers) unless names
end
+
+ [appointments, missing_providers]
end
def appointments_helper
diff --git a/modules/mobile/spec/request/appointments_vaos_v2_list_request_spec.rb b/modules/mobile/spec/request/appointments_vaos_v2_list_request_spec.rb
index 60f14b0c007..42149d33ca9 100644
--- a/modules/mobile/spec/request/appointments_vaos_v2_list_request_spec.rb
+++ b/modules/mobile/spec/request/appointments_vaos_v2_list_request_spec.rb
@@ -13,6 +13,7 @@
before do
Flipper.enable('va_online_scheduling')
allow_any_instance_of(VAOS::UserService).to receive(:session).and_return('stubbed_token')
+ allow(Rails.logger).to receive(:info)
Timecop.freeze(Time.zone.parse('2022-01-01T19:25:00Z'))
end
@@ -66,6 +67,7 @@
end
end
end
+ expect(response).to have_http_status(:ok)
location = response.parsed_body.dig('data', 0, 'attributes', 'location')
physical_location = response.parsed_body.dig('data', 0, 'attributes', 'physicalLocation')
expect(response.body).to match_json_schema('VAOS_v2_appointments')
@@ -84,6 +86,14 @@
'url' => nil,
'code' => nil })
expect(physical_location).to eq('MTZ OPC, LAB')
+ expect(response.parsed_body['meta']).to eq({
+ 'pagination' => { 'currentPage' => 1,
+ 'perPage' => 10,
+ 'totalPages' => 1,
+ 'totalEntries' => 1 },
+ 'upcomingAppointmentsCount' => 0,
+ 'upcomingDaysLimit' => 7
+ })
end
end
@@ -97,6 +107,9 @@
end
end
end
+ expect(response).to have_http_status(:ok)
+ expect(Rails.logger).to have_received(:info).with('Mobile Appointment Partial Error',
+ errors: [{ missing_facilities: ['983'] }])
expect(response.body).to match_json_schema('VAOS_v2_appointments')
location = response.parsed_body.dig('data', 0, 'attributes', 'location')
expect(location).to eq({ 'id' => nil,
@@ -155,6 +168,10 @@
end
end
end
+ expect(response).to have_http_status(:ok)
+ expect(Rails.logger).to have_received(:info).with('Mobile Appointment Partial Error',
+ errors: [{ missing_facilities: ['999AA'] },
+ { missing_clinics: ['999'] }])
expect(response.body).to match_json_schema('VAOS_v2_appointments')
expect(response.parsed_body.dig('data', 0, 'attributes', 'healthcareService')).to be_nil
end
@@ -187,6 +204,14 @@
end
expect(response).to have_http_status(:multi_status)
+ appointment_error = { errors: [{ appointment_errors: [{ system: 'the system',
+ id: 'id-string',
+ status: 'status-string',
+ code: 0,
+ trace_id: 'traceId-string',
+ message: 'msg-string',
+ detail: 'detail-string' }] }] }
+ expect(Rails.logger).to have_received(:info).with('Mobile Appointment Partial Error', appointment_error)
expect(response.parsed_body['data'].count).to eq(1)
expect(response.parsed_body['meta']).to include(
{
@@ -287,6 +312,8 @@ def fetch_appointments
end
expect(response).to have_http_status(:ok)
expect(appointment['attributes']['healthcareProvider']).to be_nil
+ expect(Rails.logger).to have_received(:info).with('Mobile Appointment Partial Error',
+ errors: [{ missing_providers: ['1407938061'] }])
end
it 'falls back to nil when provider service returns 500' do
@@ -304,6 +331,8 @@ def fetch_appointments
end
expect(response).to have_http_status(:ok)
expect(appointment['attributes']['healthcareProvider']).to be_nil
+ expect(Rails.logger).to have_received(:info).with('Mobile Appointment Partial Error',
+ errors: [{ missing_providers: ['1407938061'] }])
end
end
diff --git a/modules/mobile/spec/services/v2/appointments/provider_names_spec.rb b/modules/mobile/spec/services/v2/appointments/provider_names_spec.rb
index 526a040733f..6f4b080541b 100644
--- a/modules/mobile/spec/services/v2/appointments/provider_names_spec.rb
+++ b/modules/mobile/spec/services/v2/appointments/provider_names_spec.rb
@@ -69,27 +69,31 @@
end
it 'returns names as first_name last_name' do
- name = subject.form_names_from_appointment_practitioners_list(single_practitioner_with_name)
+ name, missing_providers = subject.form_names_from_appointment_practitioners_list(single_practitioner_with_name)
expect(name).to eq('CAROLYN KNIEFEL')
+ expect(missing_providers).to eq([])
end
it 'handles partial names predictably' do
partial_name_data = single_practitioner_with_name.first
partial_name_data[:name].delete(:given)
- name = subject.form_names_from_appointment_practitioners_list([partial_name_data])
+ name, missing_providers = subject.form_names_from_appointment_practitioners_list([partial_name_data])
expect(name).to eq('KNIEFEL')
+ expect(missing_providers).to eq([])
end
it 'aggregates multiple names as a comma separated list' do
- name = subject.form_names_from_appointment_practitioners_list(multiple_practioners_with_names)
+ name, missing_providers = subject.form_names_from_appointment_practitioners_list(multiple_practioners_with_names)
expect(name).to eq('CAROLYN KNIEFEL, MARCY NADEAU')
+ expect(missing_providers).to eq([])
end
it 'forms names from upstream when an identifier is found without a name' do
allow_any_instance_of(VAOS::V2::MobilePPMSService).to\
receive(:get_provider).with('1407938061').and_return(provider_response)
- name = subject.form_names_from_appointment_practitioners_list(practitioner_without_name)
+ name, missing_providers = subject.form_names_from_appointment_practitioners_list(practitioner_without_name)
expect(name).to eq('DEHGHAN, AMIR')
+ expect(missing_providers).to eq([])
end
it 'can request multiple upstream providers' do
@@ -107,8 +111,10 @@
receive(:get_provider).with('1407938061').and_return(provider_response)
allow_any_instance_of(VAOS::V2::MobilePPMSService).to\
receive(:get_provider).with('1407938062').and_return(second_provider_response)
- name = subject.form_names_from_appointment_practitioners_list(multiple_practitioners_without_names)
+ name, missing_providers =
+ subject.form_names_from_appointment_practitioners_list(multiple_practitioners_without_names)
expect(name).to eq('DEHGHAN, AMIR, J. Jones')
+ expect(missing_providers).to eq([])
end
it 'only requests an upstream provider once' do
@@ -121,8 +127,9 @@
it 'returns nil when the ppms service raises an error' do
allow_any_instance_of(VAOS::V2::MobilePPMSService).to\
receive(:get_provider).and_raise(Common::Exceptions::BackendServiceException)
- name = subject.form_names_from_appointment_practitioners_list(practitioner_without_name)
+ name, missing_providers = subject.form_names_from_appointment_practitioners_list(practitioner_without_name)
expect(name).to be_nil
+ expect(missing_providers).to eq(['1407938061'])
end
it 'returns nil if the returned provider does not match the expected structure' do
@@ -130,8 +137,9 @@
allow_any_instance_of(VAOS::V2::MobilePPMSService).to\
receive(:get_provider).with('1407938061').and_return(nameless_provider)
- name = subject.form_names_from_appointment_practitioners_list(practitioner_without_name)
+ name, missing_providers = subject.form_names_from_appointment_practitioners_list(practitioner_without_name)
expect(name).to be_nil
+ expect(missing_providers).to eq(['1407938061'])
end
end
end
diff --git a/modules/mobile/spec/support/schemas/VAOS_v2_appointments.json b/modules/mobile/spec/support/schemas/VAOS_v2_appointments.json
index 1a3f2ce3bc3..3d419e31c69 100644
--- a/modules/mobile/spec/support/schemas/VAOS_v2_appointments.json
+++ b/modules/mobile/spec/support/schemas/VAOS_v2_appointments.json
@@ -235,7 +235,7 @@
],
"properties": {
"errors": {
- "type": "null"
+ "type": ["array","null"]
},
"pagination": {
"type": "object",
diff --git a/modules/simple_forms_api/app/models/simple_forms_api/vba_20_10207.rb b/modules/simple_forms_api/app/models/simple_forms_api/vba_20_10207.rb
index c0b5c505672..85446b97de0 100644
--- a/modules/simple_forms_api/app/models/simple_forms_api/vba_20_10207.rb
+++ b/modules/simple_forms_api/app/models/simple_forms_api/vba_20_10207.rb
@@ -3,6 +3,7 @@
module SimpleFormsApi
class VBA2010207
include Virtus.model(nullify_blank: true)
+ STATS_KEY = 'api.simple_forms_api.20_10207'
attribute :data
@@ -97,7 +98,11 @@ def submission_date_stamps
[]
end
- def track_user_identity(confirmation_number); end
+ def track_user_identity(confirmation_number)
+ identity = "#{data['preparer_type']} #{data['third_party_type']}"
+ StatsD.increment("#{STATS_KEY}.#{identity}")
+ Rails.logger.info('Simple forms api - 20-10207 submission user identity', identity:, confirmation_number:)
+ end
private
diff --git a/modules/vaos/app/services/vaos/v2/appointments_service.rb b/modules/vaos/app/services/vaos/v2/appointments_service.rb
index 6a3eacbb338..d9bd6d153b3 100644
--- a/modules/vaos/app/services/vaos/v2/appointments_service.rb
+++ b/modules/vaos/app/services/vaos/v2/appointments_service.rb
@@ -15,6 +15,7 @@ class AppointmentsService < VAOS::SessionService
FACILITY_ERROR_MSG = 'Error fetching facility details'
AVS_ERROR_MESSAGE = 'Error retrieving AVS link'
AVS_APPT_TEST_ID = '192308'
+ MANILA_PHILIPPINES_FACILITY_ID = '358'
AVS_FLIPPER = :va_online_scheduling_after_visit_summary
ORACLE_HEALTH_CANCELLATIONS = :va_online_scheduling_enable_OH_cancellations
@@ -411,15 +412,36 @@ def convert_appointment_time(appt)
if !appt[:start].nil?
facility_timezone = get_facility_timezone_memoized(appt[:location_id])
appt[:local_start_time] = convert_utc_to_local_time(appt[:start], facility_timezone)
+
+ if appt[:location_id] == MANILA_PHILIPPINES_FACILITY_ID
+ log_timezone_info(appt[:location_id], facility_timezone, appt[:start], appt[:local_start_time])
+ end
+
elsif !appt.dig(:requested_periods, 0, :start).nil?
appt[:requested_periods].each do |period|
facility_timezone = get_facility_timezone_memoized(appt[:location_id])
period[:local_start_time] = convert_utc_to_local_time(period[:start], facility_timezone)
+
+ if appt[:location_id] == MANILA_PHILIPPINES_FACILITY_ID
+ log_timezone_info(appt[:location_id], facility_timezone, period[:start], period[:local_start_time])
+ end
end
end
appt
end
+ def log_timezone_info(appt_location_id, facility_timezone, appt_start_time_utc, appt_start_time_local)
+ Rails.logger.info(
+ "Timezone info for Manila Philippines location_id #{appt_location_id}",
+ {
+ location_id: appt_location_id,
+ facility_timezone:,
+ appt_start_time_utc:,
+ appt_start_time_local:
+ }.to_json
+ )
+ end
+
# Returns a local [DateTime] object converted from UTC using the facility's timezone offset.
# We'd like to perform this change only on the appointment responses to offer a consistently
# formatted local time to our consumers while not changing how we pass DateTimes to upstream services.
diff --git a/modules/vaos/spec/services/v2/appointment_service_spec.rb b/modules/vaos/spec/services/v2/appointment_service_spec.rb
index 5ff40013f14..88c2486408c 100644
--- a/modules/vaos/spec/services/v2/appointment_service_spec.rb
+++ b/modules/vaos/spec/services/v2/appointment_service_spec.rb
@@ -623,6 +623,68 @@
end
end
+ describe '#convert_appointment_time' do
+ let(:manila_appt) do
+ {
+ id: '12345',
+ location_id: '358',
+ start: '2024-12-20T00:00:00Z'
+ }
+ end
+
+ let(:manila_appt_req) do
+ {
+ id: '12345',
+ location_id: '358',
+ requested_periods: [{ start: '2024-12-20T00:00:00Z', end: '2024-12-20T11:59:59.999Z' }]
+ }
+ end
+
+ context 'when appt location id is 358' do
+ it 'logs the appt location id, timezone info, utc/local times of appt' do
+ allow_any_instance_of(VAOS::V2::AppointmentsService)
+ .to receive(:get_facility_timezone_memoized)
+ .and_return('Asia/Manila')
+ allow(Rails.logger).to receive(:info)
+
+ subject.send(:convert_appointment_time, manila_appt)
+ expect(Rails.logger).to have_received(:info).with('Timezone info for Manila Philippines location_id 358',
+ {
+ location_id: '358',
+ facility_timezone: 'Asia/Manila',
+ appt_start_time_utc: '2024-12-20T00:00:00Z',
+ appt_start_time_local: subject.send(
+ :convert_utc_to_local_time,
+ manila_appt[:start],
+ 'Asia/Manila'
+ )
+ }.to_json)
+ end
+
+ it 'logs the appt location id, timezone info, utc/local times of appt request' do
+ allow_any_instance_of(VAOS::V2::AppointmentsService)
+ .to receive(:get_facility_timezone_memoized)
+ .and_return('Asia/Manila')
+ allow(Rails.logger).to receive(:info)
+
+ subject.send(:convert_appointment_time, manila_appt_req)
+ expect(Rails.logger).to have_received(:info).with('Timezone info for Manila Philippines location_id 358',
+ {
+ location_id: '358',
+ facility_timezone: 'Asia/Manila',
+ appt_start_time_utc: '2024-12-20T00:00:00Z',
+ appt_start_time_local: subject.send(
+ :convert_utc_to_local_time, manila_appt_req.dig(
+ :requested_periods,
+ 0,
+ :start
+ ), 'Asia/Manila'
+ )
+ }.to_json)
+ end
+ end
+ end
+
describe '#convert_utc_to_local_time' do
let(:start_datetime) { '2021-09-02T14:00:00Z'.to_datetime }
diff --git a/spec/controllers/v0/profile/direct_deposits_controller_spec.rb b/spec/controllers/v0/profile/direct_deposits_controller_spec.rb
index 3dd8abc3e91..709a25e4e35 100644
--- a/spec/controllers/v0/profile/direct_deposits_controller_spec.rb
+++ b/spec/controllers/v0/profile/direct_deposits_controller_spec.rb
@@ -9,11 +9,28 @@
sign_in_as(user)
token = 'abcdefghijklmnop'
allow_any_instance_of(DirectDeposit::Configuration).to receive(:access_token).and_return(token)
+ allow(Rails.logger).to receive(:info)
Flipper.disable(:profile_show_direct_deposit_single_form)
end
describe '#show' do
context 'when successful' do
+ it 'logs the control info' do
+ VCR.use_cassette('lighthouse/direct_deposit/show/200_valid') do
+ get(:show)
+ end
+
+ expect(response).to have_http_status(:ok)
+ expect(Rails.logger)
+ .to have_received(:info)
+ .with('Direct Deposit Control Info: Show',
+ { benefit_type: 'both',
+ updatable: true,
+ valid: true,
+ restrictions: '',
+ errors: '' })
+ end
+
it 'returns a status of 200' do
VCR.use_cassette('lighthouse/direct_deposit/show/200_valid') do
get(:show)
@@ -154,11 +171,36 @@
control_information: {
can_update_direct_deposit: true,
is_corp_available: true,
- is_edu_claim_available: true
+ is_edu_claim_available: true,
+ is_corp_rec_found: true,
+ has_no_bdn_payments: true,
+ has_index: true,
+ is_competent: true,
+ has_mailing_address: true,
+ has_no_fiduciary_assigned: true,
+ is_not_deceased: true,
+ has_payment_address: true,
+ has_identity: true
}
}
end
+ it 'logs the control info' do
+ VCR.use_cassette('lighthouse/direct_deposit/update/200_valid') do
+ put(:update, params:)
+ end
+
+ expect(response).to have_http_status(:ok)
+ expect(Rails.logger)
+ .to have_received(:info)
+ .with('Direct Deposit Control Info: Update',
+ { benefit_type: 'both',
+ updatable: true,
+ valid: true,
+ restrictions: '',
+ errors: '' })
+ end
+
it 'returns a status of 200' do
VCR.use_cassette('lighthouse/direct_deposit/update/200_valid') do
put(:update, params:)
diff --git a/spec/lib/evss/disability_compensation_form/data_translation_all_claim_spec.rb b/spec/lib/evss/disability_compensation_form/data_translation_all_claim_spec.rb
index 0d000d350b5..88ac3800b51 100644
--- a/spec/lib/evss/disability_compensation_form/data_translation_all_claim_spec.rb
+++ b/spec/lib/evss/disability_compensation_form/data_translation_all_claim_spec.rb
@@ -1451,6 +1451,36 @@
end
end
+ describe '#add_toxic_exposure' do
+ let(:form_content) do
+ {
+ 'form526' => {
+ 'toxicExposure' => {
+ 'gulfWar1990' => {
+ 'iraq' => true,
+ 'kuwait' => true,
+ 'qatar' => true
+ }
+ }
+ }
+ }
+ end
+
+ it 'returns toxic exposure' do
+ expect(subject.send(:add_toxic_exposure)).to eq(
+ {
+ 'toxicExposure' => {
+ 'gulfWar1990' => {
+ 'iraq' => true,
+ 'kuwait' => true,
+ 'qatar' => true
+ }
+ }
+ }
+ )
+ end
+ end
+
describe '#application_expiration_date' do
it 'returns the application creation date + 365 days' do
expect(subject.send(:application_expiration_date)).to eq '2021-11-05T18:19:50Z'
diff --git a/spec/lib/lighthouse/benefits_claims/service_spec.rb b/spec/lib/lighthouse/benefits_claims/service_spec.rb
index d5ecd4fe022..05d1fe2e084 100644
--- a/spec/lib/lighthouse/benefits_claims/service_spec.rb
+++ b/spec/lib/lighthouse/benefits_claims/service_spec.rb
@@ -113,6 +113,15 @@
expect(response.claim_id).to eq(1_234_567_890)
end
end
+
+ context 'when given the option to use generate pdf' do
+ it 'calls the generate pdf endpoint' do
+ VCR.use_cassette('lighthouse/benefits_claims/submit526/200_response_generate_pdf') do
+ raw_response = @service.submit526({}, '', '', { generate_pdf: true })
+ expect(raw_response.body).to eq('No example available')
+ end
+ end
+ end
end
end
end
diff --git a/spec/lib/lighthouse/direct_deposit/control_information_spec.rb b/spec/lib/lighthouse/direct_deposit/control_information_spec.rb
index ab3cdb5db61..252bf2c7296 100644
--- a/spec/lib/lighthouse/direct_deposit/control_information_spec.rb
+++ b/spec/lib/lighthouse/direct_deposit/control_information_spec.rb
@@ -10,16 +10,32 @@
info.clear_restrictions
end
+ context 'when clear_restrictions is called' do
+ it 'is updatable' do
+ expect(info.account_updatable?).to be(true)
+ end
+ end
+
context 'when no restrictions' do
it 'is updateable' do
expect(info.account_updatable?).to be(true)
expect(info.restrictions).to be_empty
end
+
+ context 'and can_update_direct_deposit is false' do
+ it 'is invalid' do
+ info.is_edu_claim_available = true
+ info.can_update_direct_deposit = false
+
+ expect(info.valid?).to be(false)
+ expect(info.errors).to eq(['Has no restrictions. Account should be updatable.'])
+ end
+ end
end
context 'when there is a restriction' do
it 'is not updateable' do
- Lighthouse::DirectDeposit::ControlInformation::RESTRICTIONS.each do |name|
+ info.restrictions.each do |name|
info.clear_restrictions
info.send("#{name}=", false)
@@ -27,6 +43,17 @@
expect(info.restrictions).not_to be_empty
end
end
+
+ context 'and can_update_direct_deposit is true' do
+ it 'is invalid' do
+ info.is_corp_available = true
+ info.has_index = false
+ info.can_update_direct_deposit = true
+
+ expect(info.valid?).to be(false)
+ expect(info.errors).to eq(['Has restrictions. Account should not be updatable.'])
+ end
+ end
end
context 'when is_corp_available is true' do
@@ -43,30 +70,36 @@
end
end
- context 'has no benefit type' do
+ context 'when no benefit type' do
it 'is invalid' do
expect(info.valid?).to be(false)
expect(info.errors).to eq(['Missing benefit type. Must be either CnP or EDU benefits.'])
end
end
- context 'has restrictions' do
- it 'account should not be updatable' do
- info.is_edu_claim_available = true
- info.has_identity = false
+ context 'benefit type' do
+ it 'returns a benefit type of cnp' do
+ info.is_corp_available = true
+ info.is_edu_claim_available = false
+ expect(info.benefit_type).to eq('cnp')
+ end
- expect(info.valid?).to be(false)
- expect(info.errors).to eq(['Has restrictions. Account should not be updatable.'])
+ it 'returns a benefit type of edu' do
+ info.is_corp_available = false
+ info.is_edu_claim_available = true
+ expect(info.benefit_type).to eq('edu')
end
- end
- context 'has no restrictions' do
- it 'account should be updatable' do
+ it 'returns a benefit type of both' do
info.is_corp_available = true
- info.can_update_direct_deposit = false
+ info.is_edu_claim_available = true
+ expect(info.benefit_type).to eq('both')
+ end
- expect(info.valid?).to be(false)
- expect(info.errors).to eq(['Has no restrictions. Account should be updatable.'])
+ it 'returns a benefit type of none' do
+ info.is_corp_available = false
+ info.is_edu_claim_available = false
+ expect(info.benefit_type).to eq('none')
end
end
end
diff --git a/spec/models/form526_submission_spec.rb b/spec/models/form526_submission_spec.rb
index c0b9af4f2cd..0050140e3d8 100644
--- a/spec/models/form526_submission_spec.rb
+++ b/spec/models/form526_submission_spec.rb
@@ -103,6 +103,10 @@
.to(:unprocessable).on_event(:mark_as_unprocessable)
expect(submission).to transition_from(:unprocessed)
.to(:in_remediation).on_event(:begin_remediation)
+ expect(submission).to transition_from(:unprocessed)
+ .to(:processed_in_batch_remediation).on_event(:process_in_batch_remediation)
+ expect(submission).to transition_from(:unprocessed)
+ .to(:ignorable_duplicate).on_event(:ignore_as_duplicate)
end
end
diff --git a/spec/requests/disability_compensation_form_request_spec.rb b/spec/requests/disability_compensation_form_request_spec.rb
index eb08c9a4385..6825d965218 100644
--- a/spec/requests/disability_compensation_form_request_spec.rb
+++ b/spec/requests/disability_compensation_form_request_spec.rb
@@ -242,6 +242,8 @@ def test_error(cassette_path, status, headers)
post('/v0/disability_compensation_form/submit_all_claim', params: all_claims_form, headers:)
expect(response).to have_http_status(:ok)
expect(response).to match_response_schema('submit_disability_form')
+ form = Form526Submission.last.form
+ expect(form.dig('form526', 'form526', 'toxicExposure')).not_to eq(nil)
end
it 'matches the rated disabilites schema with camel-inflection' do
diff --git a/spec/support/disability_compensation_form/all_claims_fe_submission.json b/spec/support/disability_compensation_form/all_claims_fe_submission.json
index 648eff4fd18..200e53e75c2 100644
--- a/spec/support/disability_compensation_form/all_claims_fe_submission.json
+++ b/spec/support/disability_compensation_form/all_claims_fe_submission.json
@@ -144,6 +144,7 @@
]
}
],
+ "toxicExposure": {},
"waiveRetirementPay": false,
"waiveTrainingPay": true,
"hasTrainingPay": true
diff --git a/spec/support/disability_compensation_form/submissions/with_everything.json b/spec/support/disability_compensation_form/submissions/with_everything.json
index 1fb50701faa..d93f8ff4aa9 100644
--- a/spec/support/disability_compensation_form/submissions/with_everything.json
+++ b/spec/support/disability_compensation_form/submissions/with_everything.json
@@ -191,7 +191,69 @@
}
]
}
- ]
+ ],
+ "toxicExposure": {
+ "gulfWar1990": {
+ "iraq": true,
+ "kuwait": true,
+ "qatar": true
+ },
+ "gulfWar1990Details": {
+ "iraq": {
+ "startDate": "1991-03-01",
+ "endDate": "1992-01-01"
+ },
+ "qatar": {
+ "startDate": "1991-02-12",
+ "endDate": "1991-06-01"
+ },
+ "kuwait": {
+ "startDate": "1991-03-15"
+ }
+ },
+ "herbicide": {
+ "cambodia": true,
+ "guam": true,
+ "laos": true
+ },
+ "herbicideDetails": {
+ "cambodia": {
+ "startDate": "1991-03-01",
+ "endDate": "1992-01-01"
+ },
+ "guam": {
+ "startDate": "1991-02-12",
+ "endDate": "1991-06-01"
+ },
+ "laos": {
+ "startDate": "1991-03-15"
+ }
+ },
+ "otherHerbicideLocations": "freeform text field.",
+ "otherExposures": {
+ "asbestos": true,
+ "radiation": true,
+ "mustardgas": false
+ },
+ "otherExposureDetails": {
+ "asbestos": {
+ "startDate": "1991-03-01",
+ "endDate": "1992-01-01"
+ },
+ "radiation": {
+ "startDate": "1991-03-01",
+ "endDate": "1992-01-01"
+ }
+ },
+ "specifyOtherExposures": {
+ "description": "Lead, burn pits",
+ "startDate": "1991-03-01",
+ "endDate": "1992-01-01"
+ },
+ "conditions": {
+ "deviatedseptum": true
+ }
+ }
}
},
"form526_uploads": [
diff --git a/spec/support/vcr_cassettes/claims_api/bgs/veteran_representative_service/create_veteran_representative/mpi_ptcpnt_id_instead_of_vnp_ptcpnt_id.yml b/spec/support/vcr_cassettes/claims_api/bgs/veteran_representative_service/create_veteran_representative/mpi_ptcpnt_id_instead_of_vnp_ptcpnt_id.yml
new file mode 100644
index 00000000000..9314758c514
--- /dev/null
+++ b/spec/support/vcr_cassettes/claims_api/bgs/veteran_representative_service/create_veteran_representative/mpi_ptcpnt_id_instead_of_vnp_ptcpnt_id.yml
@@ -0,0 +1,233 @@
+---
+http_interactions:
+- request:
+ method: get
+ uri: "/VDC/VeteranRepresentativeService?WSDL"
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ User-Agent:
+ - Faraday v2.9.0
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Tue, 23 Apr 2024 19:25:26 GMT
+ Server:
+ - Apache
+ X-Frame-Options:
+ - SAMEORIGIN
+ Transfer-Encoding:
+ - chunked
+ Content-Type:
+ - text/xml;charset=utf-8
+ Strict-Transport-Security:
+ - max-age=16000000; includeSubDomains; preload;
+ body:
+ encoding: UTF-8
+ string: |-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ recorded_at: Mon, 22 Apr 2024 19:27:00 GMT
+- request:
+ method: post
+ uri: "/VDC/VeteranRepresentativeService"
+ body:
+ encoding: UTF-8
+ string: |
+
+
+
+
+
+ VAgovAPI
+
+
+ 127.0.0.1
+ 281
+ VAgovAPI
+ keyHere
+ keyHere
+
+
+
+
+
+
+ 21-223854909600043284074falsefalsefalsefalsefalsefalsetrueSubmittedRecognized Veterans Service Organization18235876 Crowther AveBridgeport06605CT2024-04-22T19:27:37Z
+
+
+
+
+ headers:
+ User-Agent:
+ - Faraday v2.9.0
+ Content-Type:
+ - text/xml;charset=UTF-8
+ Host:
+ - ".vba.va.gov"
+ Soapaction:
+ - '"createVeteranRepresentative"'
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ response:
+ status:
+ code: 500
+ message: Internal Server Error
+ headers:
+ Date:
+ - Tue, 23 Apr 2024 19:25:27 GMT
+ Server:
+ - Apache
+ X-Frame-Options:
+ - SAMEORIGIN
+ Transfer-Encoding:
+ - chunked
+ Content-Type:
+ - text/xml; charset=utf-8
+ Strict-Transport-Security:
+ - max-age=16000000; includeSubDomains; preload;
+ body:
+ encoding: UTF-8
+ string: 'ns0:Servergov.va.vba.benefits.exceptions.MessageFault
+
+ 3
+ :
+ ORA-02291: integrity constraint (CORPPROD.FK1_VNP_PTCPNT_RLNSHP) violated - parent key
+ not found - Input: Proc ID: 3854909, poa code = 074, formTypeCode = 21-22,
+ submittedDate: 2024-04-22T14:27:37-05:00
+
+
+ 3
+ :
+ ORA-02291: integrity constraint (CORPPROD.FK1_VNP_PTCPNT_RLNSHP) violated - parent key
+ not found - Input: Proc ID: 3854909, poa code = 074, formTypeCode = 21-22,
+ submittedDate: 2024-04-22T14:27:37-05:00
+
+
+
+
+
+ '
+ recorded_at: Mon, 22 Apr 2024 19:27:00 GMT
+recorded_with: VCR 6.2.0
diff --git a/spec/support/vcr_cassettes/claims_api/bgs/veteran_representative_service/create_veteran_representative/valid_params.yml b/spec/support/vcr_cassettes/claims_api/bgs/veteran_representative_service/create_veteran_representative/valid_params.yml
new file mode 100644
index 00000000000..767a27d1269
--- /dev/null
+++ b/spec/support/vcr_cassettes/claims_api/bgs/veteran_representative_service/create_veteran_representative/valid_params.yml
@@ -0,0 +1,280 @@
+---
+http_interactions:
+- request:
+ method: get
+ uri: "/VDC/VeteranRepresentativeService?WSDL"
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ User-Agent:
+ - Faraday v2.9.0
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Tue, 23 Apr 2024 19:07:13 GMT
+ Server:
+ - Apache
+ X-Frame-Options:
+ - SAMEORIGIN
+ Transfer-Encoding:
+ - chunked
+ Content-Type:
+ - text/xml;charset=utf-8
+ Strict-Transport-Security:
+ - max-age=16000000; includeSubDomains; preload;
+ body:
+ encoding: UTF-8
+ string: |-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ recorded_at: Mon, 22 Apr 2024 19:27:37 GMT
+- request:
+ method: post
+ uri: "/VDC/VeteranRepresentativeService"
+ body:
+ encoding: UTF-8
+ string: |
+
+
+
+
+
+ VAgovAPI
+
+
+ 127.0.0.1
+ 281
+ VAgovAPI
+ keyHere
+ keyHere
+
+
+
+
+
+
+
+ 21-22
+ 3854909
+ 182359
+ 074
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ Submitted
+ Recognized Veterans Service Organization
+ 182358
+ 76 Crowther Ave
+ Bridgeport
+ 06605
+ CT
+ 2024-04-22T19:27:37Z
+
+
+
+
+ headers:
+ User-Agent:
+ - Faraday v2.9.0
+ Content-Type:
+ - text/xml;charset=UTF-8
+ Host:
+ - ".vba.va.gov"
+ Soapaction:
+ - '"createVeteranRepresentative"'
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ Accept:
+ - "*/*"
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Tue, 23 Apr 2024 19:07:14 GMT
+ Server:
+ - Apache
+ X-Frame-Options:
+ - SAMEORIGIN
+ Transfer-Encoding:
+ - chunked
+ Content-Type:
+ - text/xml; charset=utf-8
+ Strict-Transport-Security:
+ - max-age=16000000; includeSubDomains; preload;
+ body:
+ encoding: UTF-8
+ string:
+
+ 76 Crowther Ave
+
+
+ true
+ Bridgeport
+ 182358
+
+ 21-22
+
+ false
+ false
+ false
+ false
+
+
+
+ 074
+ 06605
+ 3854909
+
+
+
+
+ Recognized Veterans Service Organization
+ false
+
+
+ CT
+ Submitted
+ 182359
+
+ VERNON
+ WAGNER
+
+
+
+
+ VERNON
+ WAGNER
+
+
+
+
+
+
+
+ recorded_at: Mon, 22 Apr 2024 19:27:37 GMT
+recorded_with: VCR 6.2.0
diff --git a/spec/support/vcr_cassettes/lighthouse/benefits_claims/submit526/200_response_generate_pdf.yml b/spec/support/vcr_cassettes/lighthouse/benefits_claims/submit526/200_response_generate_pdf.yml
new file mode 100644
index 00000000000..19741d9cff9
--- /dev/null
+++ b/spec/support/vcr_cassettes/lighthouse/benefits_claims/submit526/200_response_generate_pdf.yml
@@ -0,0 +1,85 @@
+---
+http_interactions:
+- request:
+ method: post
+ uri: https://sandbox-api.va.gov/services/claims/v2/veterans/123498767V234859/526/generatePDF/minimum-validations
+ body:
+ encoding: US-ASCII
+ string: ''
+ headers:
+ Accept:
+ - application/json
+ Content-Type:
+ - application/json
+ User-Agent:
+ - Vets.gov Agent
+ Authorization:
+ - Bearer blahblahblah
+ Accept-Encoding:
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+ response:
+ status:
+ code: 200
+ message: OK
+ headers:
+ Date:
+ - Tue, 28 Feb 2023 21:02:39 GMT
+ Content-Type:
+ - text/html; charset=utf-8
+ Connection:
+ - keep-alive
+ X-Ratelimit-Remaining-Minute:
+ - '59'
+ X-Ratelimit-Limit-Minute:
+ - '60'
+ Ratelimit-Remaining:
+ - '59'
+ Ratelimit-Limit:
+ - '60'
+ Ratelimit-Reset:
+ - '25'
+ Etag:
+ - W/"6571c42e57529000188d704a3cd1f46a"
+ Referrer-Policy:
+ - strict-origin-when-cross-origin
+ Vary:
+ - Origin
+ X-Content-Type-Options:
+ - nosniff
+ X-Download-Options:
+ - noopen
+ X-Frame-Options:
+ - SAMEORIGIN
+ X-Git-Sha:
+ - b20885293917fd081d24899644d2718d2ab4ccf9
+ X-Github-Repository:
+ - https://github.com/department-of-veterans-affairs/vets-api
+ X-Permitted-Cross-Domain-Policies:
+ - none
+ X-Request-Id:
+ - d687047e-5004-43c1-babb-c2f52f2fda40
+ X-Runtime:
+ - '3.569014'
+ X-Xss-Protection:
+ - 1; mode=block
+ Access-Control-Allow-Origin:
+ - "*"
+ X-Kong-Upstream-Latency:
+ - '3573'
+ X-Kong-Proxy-Latency:
+ - '24'
+ Via:
+ - kong/3.0.2
+ Strict-Transport-Security:
+ - max-age=31536000; includeSubDomains; preload
+ Cache-Control:
+ - no-cache, no-store
+ Pragma:
+ - no-cache
+ Transfer-Encoding:
+ - chunked
+ body:
+ encoding: ASCII-8BIT
+ string: 'No example available'
+ recorded_at: Tue, 28 Feb 2023 21:02:39 GMT
+recorded_with: VCR 6.1.0