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