diff --git a/Gemfile.lock b/Gemfile.lock
index c97180f9bf7..d347bccd1bc 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -998,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/db/migrate/20240424132506_remove_ssn_and_icn_from_vye_tables.vye.rb b/db/migrate/20240424132506_remove_ssn_and_icn_from_vye_tables.vye.rb
new file mode 100644
index 00000000000..f2fe7877b21
--- /dev/null
+++ b/db/migrate/20240424132506_remove_ssn_and_icn_from_vye_tables.vye.rb
@@ -0,0 +1,20 @@
+# This migration comes from vye (originally 20240303145700)
+class RemoveSsnAndIcnFromVyeTables < ActiveRecord::Migration[7.0]
+ def change
+ safety_assured do
+ remove_columns(
+ :vye_user_infos,
+ :icn,
+ :ssn_ciphertext,
+ :ssn_digest
+ )
+
+ remove_columns(
+ :vye_pending_documents,
+ :claim_no_ciphertext,
+ :ssn_ciphertext,
+ :ssn_digest
+ )
+ end
+ end
+end
diff --git a/db/migrate/20240424132507_remove_address_details_from_vye_user_infos.vye.rb b/db/migrate/20240424132507_remove_address_details_from_vye_user_infos.vye.rb
new file mode 100644
index 00000000000..42e3ef38cb9
--- /dev/null
+++ b/db/migrate/20240424132507_remove_address_details_from_vye_user_infos.vye.rb
@@ -0,0 +1,17 @@
+# This migration comes from vye (originally 20240305034315)
+class RemoveAddressDetailsFromVyeUserInfos < ActiveRecord::Migration[7.0]
+ def change
+ safety_assured do
+ remove_columns(
+ :vye_user_infos,
+ :full_name_ciphertext,
+ :address_line2_ciphertext,
+ :address_line3_ciphertext,
+ :address_line4_ciphertext,
+ :address_line5_ciphertext,
+ :address_line6_ciphertext,
+ :zip_ciphertext
+ )
+ end
+ end
+end
diff --git a/db/migrate/20240424132508_change_datetime_to_date.vye.rb b/db/migrate/20240424132508_change_datetime_to_date.vye.rb
new file mode 100644
index 00000000000..c8231dac316
--- /dev/null
+++ b/db/migrate/20240424132508_change_datetime_to_date.vye.rb
@@ -0,0 +1,16 @@
+# This migration comes from vye (originally 20240415205522)
+class ChangeDatetimeToDate < ActiveRecord::Migration[7.1]
+ def change
+ safety_assured do
+ change_column :vye_awards, :award_begin_date, :date
+ change_column :vye_awards, :award_end_date, :date
+ change_column :vye_awards, :payment_date, :date
+
+ change_column :vye_pending_documents, :queue_date, :date
+
+ change_column :vye_user_infos, :cert_issue_date, :date
+ change_column :vye_user_infos, :del_date, :date
+ change_column :vye_user_infos, :date_last_certified, :date
+ end
+ end
+end
diff --git a/db/migrate/20240424132509_update_verifications.vye.rb b/db/migrate/20240424132509_update_verifications.vye.rb
new file mode 100644
index 00000000000..163cefe3b10
--- /dev/null
+++ b/db/migrate/20240424132509_update_verifications.vye.rb
@@ -0,0 +1,15 @@
+# This migration comes from vye (originally 20240415220728)
+class UpdateVerifications < ActiveRecord::Migration[7.1]
+ disable_ddl_transaction!
+
+ def change
+ add_column :vye_verifications, :user_profile_id, :integer
+ add_column :vye_verifications, :monthly_rate, :decimal
+ add_column :vye_verifications, :number_hours, :integer
+ add_column :vye_verifications, :payment_date, :date
+ add_column :vye_verifications, :transact_date, :date
+ add_column :vye_verifications, :trace, :string
+
+ add_index :vye_verifications, :user_profile_id, algorithm: :concurrently
+ end
+end
diff --git a/db/migrate/20240424132510_create_vye_bdn_clones.vye.rb b/db/migrate/20240424132510_create_vye_bdn_clones.vye.rb
new file mode 100644
index 00000000000..e6ae09aeeae
--- /dev/null
+++ b/db/migrate/20240424132510_create_vye_bdn_clones.vye.rb
@@ -0,0 +1,15 @@
+# This migration comes from vye (originally 20240422033815)
+class CreateVyeBdnClones < ActiveRecord::Migration[7.1]
+ def change
+ create_table :vye_bdn_clones do |t|
+ t.boolean :is_active
+ t.boolean :export_ready
+ t.date :transact_date
+
+ t.timestamps
+ end
+
+ add_index :vye_bdn_clones, :is_active, unique: true, where: "is_active IS NOT NULL"
+ add_index :vye_bdn_clones, :export_ready, unique: true, where: "export_ready IS NOT NULL"
+ end
+end
diff --git a/db/migrate/20240424132511_add_to_vye_user_infos.vye.rb b/db/migrate/20240424132511_add_to_vye_user_infos.vye.rb
new file mode 100644
index 00000000000..f7a66eec657
--- /dev/null
+++ b/db/migrate/20240424132511_add_to_vye_user_infos.vye.rb
@@ -0,0 +1,14 @@
+# This migration comes from vye (originally 20240422043836)
+class AddToVyeUserInfos < ActiveRecord::Migration[7.1]
+ disable_ddl_transaction!
+
+ def change
+ add_column :vye_user_infos, :bdn_clone_id, :integer
+ add_column :vye_user_infos, :bdn_clone_line, :integer
+ add_column :vye_user_infos, :bdn_clone_active, :boolean
+
+ add_index :vye_user_infos, :bdn_clone_id, algorithm: :concurrently
+ add_index :vye_user_infos, :bdn_clone_line, algorithm: :concurrently
+ add_index :vye_user_infos, :bdn_clone_active, algorithm: :concurrently
+ end
+end
diff --git a/db/migrate/20240424132512_remove_from_vye_pending_document.vye.rb b/db/migrate/20240424132512_remove_from_vye_pending_document.vye.rb
new file mode 100644
index 00000000000..f430386e073
--- /dev/null
+++ b/db/migrate/20240424132512_remove_from_vye_pending_document.vye.rb
@@ -0,0 +1,8 @@
+# This migration comes from vye (originally 20240422051918)
+class RemoveFromVyePendingDocument < ActiveRecord::Migration[7.1]
+ def change
+ safety_assured do
+ remove_column :vye_pending_documents, :encrypted_kms_key
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8ef34f9a216..9db62d367e7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2024_04_17_130647) do
+ActiveRecord::Schema[7.1].define(version: 2024_04_24_132512) do
# These are extensions that must be enabled in order to support this database
enable_extension "btree_gin"
enable_extension "pg_stat_statements"
@@ -1369,10 +1369,10 @@
create_table "vye_awards", force: :cascade do |t|
t.integer "user_info_id"
t.string "cur_award_ind"
- t.datetime "award_begin_date"
- t.datetime "award_end_date"
+ t.date "award_begin_date"
+ t.date "award_end_date"
t.integer "training_time"
- t.datetime "payment_date"
+ t.date "payment_date"
t.decimal "monthly_rate"
t.string "begin_rsn"
t.string "end_rsn"
@@ -1384,6 +1384,16 @@
t.index ["user_info_id"], name: "index_vye_awards_on_user_info_id"
end
+ create_table "vye_bdn_clones", force: :cascade do |t|
+ t.boolean "is_active"
+ t.boolean "export_ready"
+ t.date "transact_date"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["export_ready"], name: "index_vye_bdn_clones_on_export_ready", unique: true, where: "(export_ready IS NOT NULL)"
+ t.index ["is_active"], name: "index_vye_bdn_clones_on_is_active", unique: true, where: "(is_active IS NOT NULL)"
+ end
+
create_table "vye_direct_deposit_changes", force: :cascade do |t|
t.integer "user_info_id"
t.string "rpo"
@@ -1405,39 +1415,24 @@
end
create_table "vye_pending_documents", force: :cascade do |t|
- t.string "ssn_digest"
- t.text "ssn_ciphertext"
- t.string "claim_no_ciphertext"
t.string "doc_type"
- t.datetime "queue_date"
+ t.date "queue_date"
t.string "rpo"
- t.text "encrypted_kms_key"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_profile_id"
- t.index ["ssn_digest"], name: "index_vye_pending_documents_on_ssn_digest"
end
create_table "vye_user_infos", force: :cascade do |t|
- t.string "icn"
- t.string "ssn_digest"
- t.text "ssn_ciphertext"
t.text "file_number_ciphertext"
t.string "suffix"
- t.text "full_name_ciphertext"
- t.text "address_line2_ciphertext"
- t.text "address_line3_ciphertext"
- t.text "address_line4_ciphertext"
- t.text "address_line5_ciphertext"
- t.text "address_line6_ciphertext"
- t.text "zip_ciphertext"
t.text "dob_ciphertext"
t.text "stub_nm_ciphertext"
t.string "mr_status"
t.string "rem_ent"
- t.datetime "cert_issue_date"
- t.datetime "del_date"
- t.datetime "date_last_certified"
+ t.date "cert_issue_date"
+ t.date "del_date"
+ t.date "date_last_certified"
t.integer "rpo_code"
t.string "fac_code"
t.decimal "payment_amt"
@@ -1446,8 +1441,12 @@
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_profile_id"
- t.index ["icn"], name: "index_vye_user_infos_on_icn"
- t.index ["ssn_digest"], name: "index_vye_user_infos_on_ssn_digest"
+ t.integer "bdn_clone_id"
+ t.integer "bdn_clone_line"
+ t.boolean "bdn_clone_active"
+ t.index ["bdn_clone_active"], name: "index_vye_user_infos_on_bdn_clone_active"
+ t.index ["bdn_clone_id"], name: "index_vye_user_infos_on_bdn_clone_id"
+ t.index ["bdn_clone_line"], name: "index_vye_user_infos_on_bdn_clone_line"
end
create_table "vye_user_profiles", force: :cascade do |t|
@@ -1472,7 +1471,14 @@
t.string "source_ind"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "user_profile_id"
+ t.decimal "monthly_rate"
+ t.integer "number_hours"
+ t.date "payment_date"
+ t.date "transact_date"
+ t.string "trace"
t.index ["user_info_id"], name: "index_vye_verifications_on_user_info_id"
+ t.index ["user_profile_id"], name: "index_vye_verifications_on_user_profile_id"
end
create_table "webhooks_notification_attempt_assocs", id: false, force: :cascade do |t|
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/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/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 9cc82b5a60e..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
@@ -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
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/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 25ff307fb6f..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
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/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/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/vye/db/migrate/20240303145700_remove_ssn_and_icn_from_vye_tables.rb b/modules/vye/db/migrate/20240303145700_remove_ssn_and_icn_from_vye_tables.rb
new file mode 100644
index 00000000000..60e78894fe5
--- /dev/null
+++ b/modules/vye/db/migrate/20240303145700_remove_ssn_and_icn_from_vye_tables.rb
@@ -0,0 +1,19 @@
+class RemoveSsnAndIcnFromVyeTables < ActiveRecord::Migration[7.0]
+ def change
+ safety_assured do
+ remove_columns(
+ :vye_user_infos,
+ :icn,
+ :ssn_ciphertext,
+ :ssn_digest
+ )
+
+ remove_columns(
+ :vye_pending_documents,
+ :claim_no_ciphertext,
+ :ssn_ciphertext,
+ :ssn_digest
+ )
+ end
+ end
+end
diff --git a/modules/vye/db/migrate/20240305034315_remove_address_details_from_vye_user_infos.rb b/modules/vye/db/migrate/20240305034315_remove_address_details_from_vye_user_infos.rb
new file mode 100644
index 00000000000..f565b836ffb
--- /dev/null
+++ b/modules/vye/db/migrate/20240305034315_remove_address_details_from_vye_user_infos.rb
@@ -0,0 +1,16 @@
+class RemoveAddressDetailsFromVyeUserInfos < ActiveRecord::Migration[7.0]
+ def change
+ safety_assured do
+ remove_columns(
+ :vye_user_infos,
+ :full_name_ciphertext,
+ :address_line2_ciphertext,
+ :address_line3_ciphertext,
+ :address_line4_ciphertext,
+ :address_line5_ciphertext,
+ :address_line6_ciphertext,
+ :zip_ciphertext
+ )
+ end
+ end
+end
diff --git a/modules/vye/db/migrate/20240415205522_change_datetime_to_date.rb b/modules/vye/db/migrate/20240415205522_change_datetime_to_date.rb
new file mode 100644
index 00000000000..849c162cb1a
--- /dev/null
+++ b/modules/vye/db/migrate/20240415205522_change_datetime_to_date.rb
@@ -0,0 +1,15 @@
+class ChangeDatetimeToDate < ActiveRecord::Migration[7.1]
+ def change
+ safety_assured do
+ change_column :vye_awards, :award_begin_date, :date
+ change_column :vye_awards, :award_end_date, :date
+ change_column :vye_awards, :payment_date, :date
+
+ change_column :vye_pending_documents, :queue_date, :date
+
+ change_column :vye_user_infos, :cert_issue_date, :date
+ change_column :vye_user_infos, :del_date, :date
+ change_column :vye_user_infos, :date_last_certified, :date
+ end
+ end
+end
diff --git a/modules/vye/db/migrate/20240415220728_update_verifications.rb b/modules/vye/db/migrate/20240415220728_update_verifications.rb
new file mode 100644
index 00000000000..0032f0ef130
--- /dev/null
+++ b/modules/vye/db/migrate/20240415220728_update_verifications.rb
@@ -0,0 +1,14 @@
+class UpdateVerifications < ActiveRecord::Migration[7.1]
+ disable_ddl_transaction!
+
+ def change
+ add_column :vye_verifications, :user_profile_id, :integer
+ add_column :vye_verifications, :monthly_rate, :decimal
+ add_column :vye_verifications, :number_hours, :integer
+ add_column :vye_verifications, :payment_date, :date
+ add_column :vye_verifications, :transact_date, :date
+ add_column :vye_verifications, :trace, :string
+
+ add_index :vye_verifications, :user_profile_id, algorithm: :concurrently
+ end
+end
diff --git a/modules/vye/db/migrate/20240422033815_create_vye_bdn_clones.rb b/modules/vye/db/migrate/20240422033815_create_vye_bdn_clones.rb
new file mode 100644
index 00000000000..289ac896503
--- /dev/null
+++ b/modules/vye/db/migrate/20240422033815_create_vye_bdn_clones.rb
@@ -0,0 +1,14 @@
+class CreateVyeBdnClones < ActiveRecord::Migration[7.1]
+ def change
+ create_table :vye_bdn_clones do |t|
+ t.boolean :is_active
+ t.boolean :export_ready
+ t.date :transact_date
+
+ t.timestamps
+ end
+
+ add_index :vye_bdn_clones, :is_active, unique: true, where: "is_active IS NOT NULL"
+ add_index :vye_bdn_clones, :export_ready, unique: true, where: "export_ready IS NOT NULL"
+ end
+end
diff --git a/modules/vye/db/migrate/20240422043836_add_to_vye_user_infos.rb b/modules/vye/db/migrate/20240422043836_add_to_vye_user_infos.rb
new file mode 100644
index 00000000000..23b81278a0f
--- /dev/null
+++ b/modules/vye/db/migrate/20240422043836_add_to_vye_user_infos.rb
@@ -0,0 +1,13 @@
+class AddToVyeUserInfos < ActiveRecord::Migration[7.1]
+ disable_ddl_transaction!
+
+ def change
+ add_column :vye_user_infos, :bdn_clone_id, :integer
+ add_column :vye_user_infos, :bdn_clone_line, :integer
+ add_column :vye_user_infos, :bdn_clone_active, :boolean
+
+ add_index :vye_user_infos, :bdn_clone_id, algorithm: :concurrently
+ add_index :vye_user_infos, :bdn_clone_line, algorithm: :concurrently
+ add_index :vye_user_infos, :bdn_clone_active, algorithm: :concurrently
+ end
+end
diff --git a/modules/vye/db/migrate/20240422051918_remove_from_vye_pending_document.rb b/modules/vye/db/migrate/20240422051918_remove_from_vye_pending_document.rb
new file mode 100644
index 00000000000..0b87976e9aa
--- /dev/null
+++ b/modules/vye/db/migrate/20240422051918_remove_from_vye_pending_document.rb
@@ -0,0 +1,7 @@
+class RemoveFromVyePendingDocument < ActiveRecord::Migration[7.1]
+ def change
+ safety_assured do
+ remove_column :vye_pending_documents, :encrypted_kms_key
+ end
+ end
+end
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/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/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