From e6968050e8e33fe34ceb032afc1c7184b5b6407c Mon Sep 17 00:00:00 2001 From: Dick Davis Date: Thu, 25 Apr 2024 15:34:13 -0500 Subject: [PATCH 1/4] 81092: Refactor Client Config Memoization (#16490) --- app/controllers/v0/sign_in_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/v0/sign_in_controller.rb b/app/controllers/v0/sign_in_controller.rb index ebfb30e273a..20b805e4d22 100644 --- a/app/controllers/v0/sign_in_controller.rb +++ b/app/controllers/v0/sign_in_controller.rb @@ -369,7 +369,8 @@ def cookie_authentication?(client_id) end def client_config(client_id) - @client_config ||= SignIn::ClientConfig.find_by(client_id:) + @client_config ||= {} + @client_config[client_id] ||= SignIn::ClientConfig.find_by(client_id:) end def sign_in_logger From beb6c787066d860cc9712d0ce67e6254ef53caa7 Mon Sep 17 00:00:00 2001 From: Rachal Cassity Date: Thu, 25 Apr 2024 15:43:49 -0500 Subject: [PATCH 2/4] Revert "creates data to seed dev & staging (#16502)" (#16506) This reverts commit c2cc95b3d0103a67ef7a8ebacf66fe9d66a0088c. --- modules/vye/app/models/vye/user_info.rb | 5 +- modules/vye/lib/tasks/vye.rake | 58 ------- modules/vye/lib/vye/staging_data/build.rb | 154 ------------------ .../vye/spec/factories/vye/address_changes.rb | 9 - .../spec/lib/vye/staging_data/build_spec.rb | 44 ----- .../verification_serializer_spec.rb | 15 -- 6 files changed, 4 insertions(+), 281 deletions(-) delete mode 100644 modules/vye/lib/vye/staging_data/build.rb delete mode 100644 modules/vye/spec/lib/vye/staging_data/build_spec.rb delete mode 100644 modules/vye/spec/serializers/verification_serializer_spec.rb diff --git a/modules/vye/app/models/vye/user_info.rb b/modules/vye/app/models/vye/user_info.rb index 4cae7864942..a50ce81e882 100644 --- a/modules/vye/app/models/vye/user_info.rb +++ b/modules/vye/app/models/vye/user_info.rb @@ -27,7 +27,6 @@ class Vye::UserInfo < ApplicationRecord enum indicator: { chapter1606: 'A', chapter1607: 'E', chapter30: 'B', D: 'D' } delegate :icn, to: :user_profile, allow_nil: true - delegate :ssn, to: :mpi_profile, allow_nil: true delegate :pending_documents, to: :user_profile delegate :verifications, to: :user_profile @@ -46,6 +45,10 @@ def verification_required verifications.empty? end + def ssn + mpi_profile&.ssn + end + private def mpi_profile diff --git a/modules/vye/lib/tasks/vye.rake b/modules/vye/lib/tasks/vye.rake index a9674415cdc..e82afb3abf4 100644 --- a/modules/vye/lib/tasks/vye.rake +++ b/modules/vye/lib/tasks/vye.rake @@ -1,15 +1,6 @@ # frozen_string_literal: true namespace :vye do - namespace :feature do - desc 'Enables request_allowed feature flag' - task request_allowed: :environment do |_cmd, _args| - current_state = Flipper.enabled?(:vye_request_allowed) - puts format('Current state vye_request_allowed is: %s', current_state:) - Flipper.enable :vye_request_allowed - end - end - namespace :install do desc 'Installs config into config/settings.local.yml' task config: :environment do |_cmd, _args| @@ -22,53 +13,4 @@ namespace :vye do local_path.write(engine_dev_path.read, mode: 'a') end end - - namespace :data do - desc 'Clear VYE data from the database' - task clear: :environment do |_cmd, _args| - Vye::AddressChange.destroy_all - Vye::DirectDepositChange.destroy_all - Vye::Verification.destroy_all - Vye::Award.destroy_all - Vye::UserInfo.destroy_all - - Vye::PendingDocument.destroy_all - - Vye::UserProfile.destroy_all - end - - desc 'Build YAML files to load for development from team sensitive data' - task build: :environment do |_cmd, _args| - source = Pathname('/projects/va.gov-team-sensitive') - target = Rails.root / 'tmp' - handles = nil - - build = Vye::StagingData::Build.new(target:) do |paths| - handles = - paths - .transform_values do |value| - (source / value).open - end - end - - build.dump - handles.each_value(&:close) - end - - desc 'Load development YAML files into the database' - task :load, [:path] => :environment do |_cmd, args| - raise 'load path is required' if args[:path].nil? - - root = Pathname(args[:path]) - files = root.glob('**/*.yaml') - raise "No files found in #{root}" if files.empty? - - files.each do |file| - source = :team_sensitive - data = YAML.safe_load(file.read, permitted_classes: [Date, DateTime, Symbol, Time]) - records = data.slice(:profile, :info, :address, :awards, :pending_documents) - Vye::LoadData.new(source:, records:) - end - end - end end diff --git a/modules/vye/lib/vye/staging_data/build.rb b/modules/vye/lib/vye/staging_data/build.rb deleted file mode 100644 index 36ae85826f4..00000000000 --- a/modules/vye/lib/vye/staging_data/build.rb +++ /dev/null @@ -1,154 +0,0 @@ -# frozen_string_literal: true - -module Vye - module StagingData - class Build - MAX_AWARD_COUNT = 4 - MAX_PENDING_DOCUMENT_COUNT = 1 - PATHS = - { - test_users: 'Administrative/vagov-users/test_users.csv', - mvi_staging_users: 'Administrative/vagov-users/mvi-staging-users.csv' - }.freeze - - private_constant :PATHS, :MAX_AWARD_COUNT, :MAX_PENDING_DOCUMENT_COUNT - - def dump - @dump if defined?(@dump) - - rows.each do |row| - summary = row[:summary] - path = root / format('%s.yaml', summary[:full_name].downcase.gsub(/\s+/, '-')) - path.write(row.to_yaml) - end - - @dump = true - end - - private - - attr_reader :test_users, :mvi_staging_users, :target - - def initialize(target:) - yield(PATHS) => {test_users:, mvi_staging_users:} - @test_users = CSV.new(test_users, headers: true).each.to_a - @mvi_staging_users = CSV.new(mvi_staging_users, headers: true).each.to_a - @target = target - end - - def cross - return @cross if defined?(@cross) - - product = - test_users - .product(mvi_staging_users) - .select do |tu, msu| - tu['ssn'] == msu['ssn'] - end - - @cross = product.group_by { |x| x.first['ssn'] }.values.pluck(0) - end - - def rows - @rows ||= - cross - .map do |tu, msu| - tu = extract_from_tu(tu) - msu = extract_from_msu(msu) - - summary = {}.merge(tu).merge(msu) - - { - summary:, - profile: fake_user_profile(summary:), - info: fake_user_info(summary:), - address: fake_address_change(summary:), - awards: fake_awards, - pending_documents: fake_pending_documents - } - end - end - - def root - return @root if defined?(@root) - - timestamp = Time.zone.now.strftime('%Y%m%dT%H%M%S%z') - root = target / format('vye/staging-data-%s', timestamp:) - root.mkpath - - @root = root - end - - def fake_user_profile(summary:) - FactoryBot.attributes_for(:vye_user_profile).except(:ssn, :icn, :file_number).tap do |record| - record[:ssn] = summary[:ssn] - record[:file_number] = summary[:ssn] - record[:icn] = summary[:icn] - end - end - - def fake_user_info(summary:) - FactoryBot.attributes_for(:vye_user_info).except(:full_name).tap do |record| - name = summary[:full_name] - parts = name.split(/\s+/) - initials = parts.pluck(0).join - rest = parts[-1][1..(7 - initials.length)] - stub_nm = [initials, rest].join.upcase - - record[:stub_nm] = stub_nm - record[:file_number] = summary[:ssn] - end - end - - def fake_address_change(summary:) - FactoryBot.attributes_for(:vye_address_backend).tap do |record| - record[:veteran_name] = summary[:full_name] - end - end - - def fake_awards - (1..rand(1..4)).map do - FactoryBot.attributes_for(:vye_award) - end - end - - def fake_pending_documents - (0..rand(0..1)).map do - FactoryBot.attributes_for(:vye_pending_document) - end - end - - def extract_from_tu(row) - ssn = scrub_ssn(row['ssn']) - idme_uuid = row['idme_uuid']&.strip - email = row['email']&.strip - password = row['password']&.strip - full_name = - row.values_at( - 'first_name', - 'middle_name', - 'last_name' - ).compact.map(&:strip).map(&:capitalize).join(' ').strip - - { ssn:, idme_uuid:, email:, password:, full_name: } - end - - def extract_from_msu(row) - ssn = scrub_ssn(row['ssn']) - icn = row['icn']&.strip - full_name = - row.values_at( - 'first_name', - 'middle_name', - 'last_name' - ).compact.map(&:strip).map(&:capitalize).join(' ').strip - - { ssn:, icn:, full_name: } - end - - def scrub_ssn(value) - value&.gsub(/\D/, '')&.strip - end - end - end -end diff --git a/modules/vye/spec/factories/vye/address_changes.rb b/modules/vye/spec/factories/vye/address_changes.rb index 6c3a882994e..40bc66818a8 100644 --- a/modules/vye/spec/factories/vye/address_changes.rb +++ b/modules/vye/spec/factories/vye/address_changes.rb @@ -9,13 +9,4 @@ zip_code { Faker::Address.zip_code } origin { Vye::AddressChange.origins['frontend'] } end - - factory :vye_address_backend, class: 'Vye::AddressChange' do - veteran_name { Faker::Name.name } - address1 { Faker::Address.street_address } - city { Faker::Address.city } - state { Faker::Address.state_abbr } - zip_code { Faker::Address.zip_code } - origin { Vye::AddressChange.origins['backend'] } - end end diff --git a/modules/vye/spec/lib/vye/staging_data/build_spec.rb b/modules/vye/spec/lib/vye/staging_data/build_spec.rb deleted file mode 100644 index f6555bfdf0e..00000000000 --- a/modules/vye/spec/lib/vye/staging_data/build_spec.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Vye::StagingData::Build do - describe '#dump' do - let(:target) { double('Pathname (Target)') } - - let(:source) { double('Pathname (Source)') } - - let(:streams) do - { - test_users: StringIO.new(<<~TEST_USERS), - first_name,middle_name,last_name,gender,birth_date,ssn,phone,email,password,mfa_code,id_types,loa,idme_uuid,logingov_uuid,services,notes - John,A,Doe,M,1932-02-05T00:00:00-08:00,111111111,800-827-1000,user1@email.com,xxx,xxx,"idme,logingov",3,xxx,xxx,"notes", - Jane,B,Smith,M,1933-04-05T00:00:00-08:00,222222222,800-827-1000,user2@email.com,xxx,xxx,"idme,logingov",3,xxx,xxx,"notes", - TEST_USERS - mvi_staging_users: StringIO.new(<<~MVI_STAGING_USERS) - first_name,middle_name,last_name,gender,birth_date,ssn,phone,email,password,icn,edipi,has_data_for, notes - John,A,Doe,M,1932-02-05T00:00:00-08:00,111111111,800-827-1000,user1@email.com,xxx,xxx,xxx,,notes - Jane,B,Smith,M,1933-04-05T00:00:00-08:00,222222222,800-827-1000,user2@email.com,xxx,xxx,xxx,, - MVI_STAGING_USERS - }.freeze - end - - let(:staging_data_build) do - Vye::StagingData::Build.new(target:) do |_paths| - streams - end - end - - it 'returns an array of rows' do - root = double('Pathname (Root)') - dump_file = double('Pathname (File)') - - expect(target).to receive(:/).and_return(root) - expect(root).to receive(:mkpath).with(no_args).and_return(true) - expect(root).to receive(:/).twice.with(any_args).and_return(dump_file) - expect(dump_file).to receive(:write).twice.and_return(true) - - staging_data_build.dump - end - end -end diff --git a/modules/vye/spec/serializers/verification_serializer_spec.rb b/modules/vye/spec/serializers/verification_serializer_spec.rb deleted file mode 100644 index f614e1e1cb5..00000000000 --- a/modules/vye/spec/serializers/verification_serializer_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Vye::VerificationSerializer, type: :serializer do - let(:resource) { build(:vye_verification) } # Assuming you have a factory for verification - let(:serializer) { described_class.new(resource) } - let(:serialization) { ActiveModelSerializers::Adapter.create(serializer, {}) } - - it 'includes the expected attributes' do - expect do - serialization.as_json - end.not_to raise_error - end -end From 9825dabdd14c9d2d2d46f2a26ff9d6aff7360948 Mon Sep 17 00:00:00 2001 From: Rachal Cassity Date: Thu, 25 Apr 2024 15:53:37 -0500 Subject: [PATCH 3/4] Revert "post database updates (#16500)" (#16507) This reverts commit c8354ff962b226343d4bb58fd3596313ede8183c. --- .../vye/v1/verifications_controller.rb | 4 +-- modules/vye/app/models/vye/address_change.rb | 12 +------- modules/vye/app/models/vye/award.rb | 1 - modules/vye/app/models/vye/bdn_clone.rb | 4 --- .../vye/app/models/vye/pending_document.rb | 2 +- modules/vye/app/models/vye/user_info.rb | 6 ++-- modules/vye/app/models/vye/user_profile.rb | 20 ++++++++----- modules/vye/app/models/vye/verification.rb | 30 ++++++++----------- modules/vye/spec/factories/vye/awards.rb | 2 -- modules/vye/spec/factories/vye/bdn_clones.rb | 8 ----- modules/vye/spec/factories/vye/user_infos.rb | 1 - .../vye/spec/factories/vye/user_profiles.rb | 2 +- .../vye/spec/factories/vye/verifications.rb | 3 -- modules/vye/spec/models/vye/bdn_clone_spec.rb | 15 ---------- .../vye/spec/models/vye/verification_spec.rb | 12 ++++---- .../requests/vye/v1/verify/create_spec.rb | 6 ++-- 16 files changed, 40 insertions(+), 88 deletions(-) delete mode 100644 modules/vye/app/models/vye/bdn_clone.rb delete mode 100644 modules/vye/spec/factories/vye/bdn_clones.rb delete mode 100644 modules/vye/spec/models/vye/bdn_clone_spec.rb diff --git a/modules/vye/app/controllers/vye/v1/verifications_controller.rb b/modules/vye/app/controllers/vye/v1/verifications_controller.rb index 413c53f6ade..40fc32ae139 100644 --- a/modules/vye/app/controllers/vye/v1/verifications_controller.rb +++ b/modules/vye/app/controllers/vye/v1/verifications_controller.rb @@ -12,9 +12,7 @@ class Vye::V1::VerificationsController < Vye::V1::ApplicationController def create authorize user_info, policy_class: UserInfoPolicy - award = user_info.awards.first - user_profile = user_info.user_profile - Verification.create!(source_ind:, award:, user_profile:) + user_info.verifications.create!(source_ind:) end private diff --git a/modules/vye/app/models/vye/address_change.rb b/modules/vye/app/models/vye/address_change.rb index 5ebeab75929..6a0b2f0c649 100644 --- a/modules/vye/app/models/vye/address_change.rb +++ b/modules/vye/app/models/vye/address_change.rb @@ -23,17 +23,7 @@ class Vye::AddressChange < ApplicationRecord presence: true, if: -> { origin == 'backend' } ) - enum origin: { - - frontend: 'f', - - # This is a special case where the record was created on the frontend - # but will not have been reflected from the backend yet - cached: 'c', - - backend: 'b' - - } + enum origin: { frontend: 'f', backend: 'b' } scope :created_today, lambda { includes(user_info: :user_profile) diff --git a/modules/vye/app/models/vye/award.rb b/modules/vye/app/models/vye/award.rb index f7755be9089..f37db8962a3 100644 --- a/modules/vye/app/models/vye/award.rb +++ b/modules/vye/app/models/vye/award.rb @@ -3,7 +3,6 @@ module Vye class Vye::Award < ApplicationRecord belongs_to :user_info - has_many :verifications, dependent: :nullify enum cur_award_ind: { current: 'C', future: 'F', past: 'P' } diff --git a/modules/vye/app/models/vye/bdn_clone.rb b/modules/vye/app/models/vye/bdn_clone.rb deleted file mode 100644 index 1ae8895f9e1..00000000000 --- a/modules/vye/app/models/vye/bdn_clone.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true - -class Vye::BdnClone < ApplicationRecord -end diff --git a/modules/vye/app/models/vye/pending_document.rb b/modules/vye/app/models/vye/pending_document.rb index 7130c96b84b..c94555c2cdc 100644 --- a/modules/vye/app/models/vye/pending_document.rb +++ b/modules/vye/app/models/vye/pending_document.rb @@ -2,7 +2,7 @@ module Vye class Vye::PendingDocument < ApplicationRecord - self.ignored_columns += %i[claim_no_ciphertext encrypted_kms_key ssn_ciphertext ssn_digest] + self.ignored_columns += %i[claim_no_ciphertext ssn_ciphertext ssn_digest] belongs_to :user_profile diff --git a/modules/vye/app/models/vye/user_info.rb b/modules/vye/app/models/vye/user_info.rb index a50ce81e882..a846faf238d 100644 --- a/modules/vye/app/models/vye/user_info.rb +++ b/modules/vye/app/models/vye/user_info.rb @@ -20,15 +20,13 @@ class Vye::UserInfo < ApplicationRecord has_many :address_changes, dependent: :destroy has_many :awards, dependent: :destroy has_many :direct_deposit_changes, dependent: :destroy - - scope :with_bdn_clone_active, -> { where(bdn_clone_active: true) } + has_many :verifications, dependent: :destroy enum mr_status: { active: 'A', expired: 'E' } enum indicator: { chapter1606: 'A', chapter1607: 'E', chapter30: 'B', D: 'D' } delegate :icn, to: :user_profile, allow_nil: true - delegate :pending_documents, to: :user_profile - delegate :verifications, to: :user_profile + delegate :pending_documents, to: :user_profile, allow_nil: true has_kms_key has_encrypted(:dob, :file_number, :stub_nm, key: :kms_key, **lockbox_options) diff --git a/modules/vye/app/models/vye/user_profile.rb b/modules/vye/app/models/vye/user_profile.rb index d4e7265339f..2c5119fc63f 100644 --- a/modules/vye/app/models/vye/user_profile.rb +++ b/modules/vye/app/models/vye/user_profile.rb @@ -4,15 +4,17 @@ class Vye::UserProfile < ApplicationRecord include Vye::DigestProtected has_many :user_infos, dependent: :restrict_with_exception - has_one( - :active_user_info, - -> { with_bdn_clone_active }, - class_name: 'Vye::UserInfo', - inverse_of: :user_profile, + + has_many( + :active_user_infos, + lambda { + order(created_at: :desc).limit(1) + }, + class_name: 'Vye::UserInfo', inverse_of: :user_profile, dependent: :restrict_with_exception ) + has_many :pending_documents, dependent: :restrict_with_exception - has_many :verifications, dependent: :restrict_with_exception digest_attribute :ssn digest_attribute :file_number @@ -26,7 +28,11 @@ class Vye::UserProfile < ApplicationRecord end end - scope :with_assos, -> { includes(:pending_documents, :verifications, active_user_info: %i[address_changes awards]) } + scope :with_assos, -> { includes(:pending_documents, active_user_infos: %i[address_changes awards verifications]) } + + def active_user_info + active_user_infos.first + end def self.find_and_update_icn(user:) return if user.blank? diff --git a/modules/vye/app/models/vye/verification.rb b/modules/vye/app/models/vye/verification.rb index 9e1ef5316cf..99e903b1917 100644 --- a/modules/vye/app/models/vye/verification.rb +++ b/modules/vye/app/models/vye/verification.rb @@ -2,29 +2,25 @@ module Vye class Vye::Verification < ApplicationRecord - belongs_to :user_profile - belongs_to :award, optional: true + belongs_to :user_info validates(:source_ind, presence: true) enum source_ind: { web: 'W', phone: 'P' } + scope :created_today, -> { includes(:user_info).where('created_at >= ?', Time.zone.now.beginning_of_day) } + def self.todays_verifications - UserInfo - .joins(awards: :verifications) - .includes(awards: :verifications) - .distinct - .each_with_object([]) do |user_info, result| - verification = user_info.awards.map(&:verifications).flatten.first - result << { - stub_nm: user_info.stub_nm, - ssn: user_info.ssn, - transact_date: verification.created_at.strftime('%Y%m%d'), - rpo_code: user_info.rpo_code, - indicator: user_info.indicator, - source_ind: verification.source_ind - } - end + created_today.each_with_object([]) do |record, result| + result << { + stub_nm: record.user_info.stub_nm, + ssn: record.user_info.ssn, + transact_date: record.created_at.strftime('%Y%m%d'), + rpo_code: record.user_info.rpo_code, + indicator: record.user_info.indicator, + source_ind: record.source_ind + } + end end def self.todays_verifications_report diff --git a/modules/vye/spec/factories/vye/awards.rb b/modules/vye/spec/factories/vye/awards.rb index 4411fc2f099..06e09afaf7a 100644 --- a/modules/vye/spec/factories/vye/awards.rb +++ b/modules/vye/spec/factories/vye/awards.rb @@ -2,8 +2,6 @@ FactoryBot.define do factory :vye_award, class: 'Vye::Award' do - association :user_info, factory: :vye_user_info - cur_award_ind { Vye::Award.cur_award_inds.values.sample } award_begin_date { DateTime.now } award_end_date { DateTime.now + 1.month } diff --git a/modules/vye/spec/factories/vye/bdn_clones.rb b/modules/vye/spec/factories/vye/bdn_clones.rb deleted file mode 100644 index 482a4db9704..00000000000 --- a/modules/vye/spec/factories/vye/bdn_clones.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -FactoryBot.define do - factory :vye_bdn_clone, class: 'Vye::BdnClone' do - is_active { true } - export_ready { false } - end -end diff --git a/modules/vye/spec/factories/vye/user_infos.rb b/modules/vye/spec/factories/vye/user_infos.rb index a864f672c97..20176580da1 100644 --- a/modules/vye/spec/factories/vye/user_infos.rb +++ b/modules/vye/spec/factories/vye/user_infos.rb @@ -22,6 +22,5 @@ fac_code { Faker::Lorem.word } payment_amt { Faker::Number.decimal(l_digits: 4, r_digits: 2) } indicator { Vye::UserInfo.indicators.values.sample } - bdn_clone_active { true } end end diff --git a/modules/vye/spec/factories/vye/user_profiles.rb b/modules/vye/spec/factories/vye/user_profiles.rb index a887e216c95..673eef21678 100644 --- a/modules/vye/spec/factories/vye/user_profiles.rb +++ b/modules/vye/spec/factories/vye/user_profiles.rb @@ -6,6 +6,6 @@ factory :vye_user_profile, class: 'Vye::UserProfile' do ssn { (1..9).map(&digit).join } file_number { (1..9).map(&digit).join } - icn { SecureRandom.uuid } + icn { 'random-icn' } end end diff --git a/modules/vye/spec/factories/vye/verifications.rb b/modules/vye/spec/factories/vye/verifications.rb index f82142385b3..4cee53aaf16 100644 --- a/modules/vye/spec/factories/vye/verifications.rb +++ b/modules/vye/spec/factories/vye/verifications.rb @@ -2,9 +2,6 @@ FactoryBot.define do factory :vye_verification, class: 'Vye::Verification' do - association :user_profile, factory: :vye_user_profile - association :award, factory: :vye_award - source_ind { Vye::Verification.source_inds.values.sample } end end diff --git a/modules/vye/spec/models/vye/bdn_clone_spec.rb b/modules/vye/spec/models/vye/bdn_clone_spec.rb deleted file mode 100644 index 67c51b88bbb..00000000000 --- a/modules/vye/spec/models/vye/bdn_clone_spec.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe Vye::BdnClone, type: :model do - describe 'create' do - let(:attributes) { FactoryBot.attributes_for(:vye_bdn_clone) } - - it 'creates a record' do - expect do - described_class.create!(attributes) - end.to change(described_class, :count).by(1) - end - end -end diff --git a/modules/vye/spec/models/vye/verification_spec.rb b/modules/vye/spec/models/vye/verification_spec.rb index 14af09e52ba..9a545b36c70 100644 --- a/modules/vye/spec/models/vye/verification_spec.rb +++ b/modules/vye/spec/models/vye/verification_spec.rb @@ -3,22 +3,20 @@ require 'rails_helper' RSpec.describe Vye::Verification, type: :model do + let(:user_info) { create(:vye_user_info) } + describe 'create' do - let!(:user_profile) { FactoryBot.create(:vye_user_profile) } - let(:verification) { FactoryBot.build(:vye_verification, user_profile:) } + let(:attributes) { FactoryBot.attributes_for(:vye_verification, user_info:) } it 'creates a record' do expect do - verification.save! + Vye::Verification.create!(attributes) end.to change(Vye::Verification, :count).by(1) end end describe 'show todays verifications' do - let!(:user_profile) { FactoryBot.create(:vye_user_profile) } - let!(:user_info) { FactoryBot.create(:vye_user_info, user_profile:) } - let!(:award) { FactoryBot.create(:vye_award, user_info:) } - let!(:verification) { FactoryBot.create(:vye_verification, award:, user_profile:) } + let!(:verification) { FactoryBot.create(:vye_verification, user_info:) } before do ssn = '123456789' diff --git a/modules/vye/spec/requests/vye/v1/verify/create_spec.rb b/modules/vye/spec/requests/vye/v1/verify/create_spec.rb index 9e33dad14b3..c98fcb71d97 100644 --- a/modules/vye/spec/requests/vye/v1/verify/create_spec.rb +++ b/modules/vye/spec/requests/vye/v1/verify/create_spec.rb @@ -47,11 +47,11 @@ describe 'in VYE' do let!(:user_profile) { FactoryBot.create(:vye_user_profile, icn: current_user.icn) } let!(:user_info) { FactoryBot.create(:vye_user_info, user_profile:) } - let!(:award) { FactoryBot.create(:vye_award, user_info:) } + let(:award) { FactoryBot.create(:vye_award, user_info:) } it 'creates a new verification' do post('/vye/v1/verify', params: {}) - + # puts JSON.pretty_generate(JSON.parse(response)) expect(response).to have_http_status(:no_content) end end @@ -63,7 +63,7 @@ end let!(:user_profile) { FactoryBot.create(:vye_user_profile, icn: current_user.icn) } let!(:user_info) { FactoryBot.create(:vye_user_info, user_profile:) } - let!(:award) { create(:vye_award, user_info:) } + let(:award) { create(:vye_award, user_info:) } it 'creates a new verification' do post('/vye/v1/verify', params: ivr_params) From 15552a869121482369fb7db3df027b6bb865e2c0 Mon Sep 17 00:00:00 2001 From: Khoa Nguyen <134089461+Khoa-V-Nguyen@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:18:57 -0600 Subject: [PATCH 4/4] BE | Ask Va Api: Update `Correspondences::Retriever` and `Inquiries::Retriever` (#16510) * Update `Correspondences::Retriever` and `Inquiries::Retriever` - `Inquiries::Retriever` is returning `correspondences` as an empty array instead of `erroring` - clean up specs as well * fix linting --------- Co-authored-by: khoa-v-nguyen --- .../ask_va_api/correspondences/retriever.rb | 25 ++++--- .../app/lib/ask_va_api/inquiries/retriever.rb | 16 +++-- .../correspondences/retriever_spec.rb | 17 ++--- .../ask_va_api/inquiries/retriever_spec.rb | 68 +++++++++++++++++++ .../spec/requests/v0/inquiries_spec.rb | 6 +- .../spec/services/crm/crm_token_spec.rb | 2 +- .../spec/services/crm/service_spec.rb | 46 +------------ 7 files changed, 104 insertions(+), 76 deletions(-) diff --git a/modules/ask_va_api/app/lib/ask_va_api/correspondences/retriever.rb b/modules/ask_va_api/app/lib/ask_va_api/correspondences/retriever.rb index f62f4368663..b8750126ba0 100644 --- a/modules/ask_va_api/app/lib/ask_va_api/correspondences/retriever.rb +++ b/modules/ask_va_api/app/lib/ask_va_api/correspondences/retriever.rb @@ -2,20 +2,27 @@ module AskVAApi module Correspondences - class CorrespondencesRetrieverError < StandardError; end - - class Retriever < BaseRetriever - attr_reader :inquiry_id, :entity_class + class Retriever + attr_reader :inquiry_id, :entity_class, :user_mock_data def initialize(inquiry_id:, user_mock_data:, entity_class:) - super(user_mock_data:, entity_class:) + @user_mock_data = user_mock_data + @entity_class = entity_class @inquiry_id = inquiry_id end + def call + case fetch_data + when Array + fetch_data.map { |data| entity_class.new(data) } + else + fetch_data + end + end + private def fetch_data - validate_input(inquiry_id, 'Invalid Inquiry ID') if user_mock_data data = File.read('modules/ask_va_api/config/locales/get_replies_mock_data.json') @@ -29,10 +36,6 @@ def fetch_data end end - def validate_input(input, error_message) - raise ArgumentError, error_message if input.blank? - end - def filter_data(data) data.select do |cor| cor[:InquiryId] == inquiry_id @@ -40,7 +43,7 @@ def filter_data(data) end def handle_response_data(response) - response[:Data].presence || raise(CorrespondencesRetrieverError, response[:Message]) + response[:Data].presence || response end end 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 073c35f8832..1ebc679f679 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 @@ -38,11 +38,18 @@ def fetch_data(id = nil) end def fetch_correspondences(inquiry_id:) - Correspondences::Retriever.new( + correspondences = Correspondences::Retriever.new( inquiry_id:, user_mock_data:, entity_class: AskVAApi::Correspondences::Entity ).call + + case correspondences + when Hash + [] + else + correspondences + end end def read_mock_data(file_name) @@ -57,12 +64,7 @@ def filter_data(data, id = nil) end def handle_response_data(response) - if response[:Data].nil? - error = JSON.parse(response[:body], symbolize_names: true) - raise InquiriesRetrieverError, error[:Message] - else - response[:Data] - end + response[:Data].presence || raise(InquiriesRetrieverError, response) end end end diff --git a/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/retriever_spec.rb b/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/retriever_spec.rb index 3eed7120732..61b84f11798 100644 --- a/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/retriever_spec.rb +++ b/modules/ask_va_api/spec/app/lib/ask_va_api/correspondences/retriever_spec.rb @@ -18,15 +18,6 @@ end describe '#call' do - context 'when id is blank' do - let(:inquiry_id) { nil } - - it 'raises an ArgumentError' do - expect { retriever.call } - .to raise_error(ErrorHandler::ServiceError, 'ArgumentError: Invalid Inquiry ID') - end - end - context 'when Crm raise an error' do let(:endpoint) { 'inquiries/1/replies' } let(:response) do @@ -42,8 +33,12 @@ allow(service).to receive(:call).and_return(response) end - it 'raise CorrespondenceRetrieverError' do - expect { retriever.call }.to raise_error(ErrorHandler::ServiceError) + it 'returns the error' do + expect(retriever.call).to eq({ Data: [], + Message: 'Data Validation: No Inquiry Found', + ExceptionOccurred: true, + ExceptionMessage: 'Data Validation: No Inquiry Found', + MessageId: '2d746074-9e5c-4987-a894-e3f834b156b5' }) 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 ee1f4e45987..910f5232db0 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 @@ -164,6 +164,74 @@ end end end + + context 'with Correspondences' do + let(:id) { '123' } + let(:response) do + { Data: [{ Id: '154163f2-8fbb-ed11-9ac4-00155da17a6f', + InquiryNumber: 'A-20230305-306178', + InquiryStatus: 'Reopened', + SubmitterQuestion: 'test', + LastUpdate: '4/1/2024 12:00:00 AM', + InquiryHasAttachments: true, + InquiryHasBeenSplit: true, + VeteranRelationship: 'GIBillBeneficiary', + SchoolFacilityCode: '77a51029-6816-e611-9436-0050568d743d', + InquiryTopic: 'Medical Care Concerns at a VA Medical Facility', + InquiryLevelOfAuthentication: 'Unauthenticated', + AttachmentNames: [{ Id: '367e8d31-6c82-1d3c-81b8-dd2cabed7555', + Name: 'Test.txt' }] }] } + end + + context 'when Correspondence::Retriever returns an error' do + before do + allow_any_instance_of(Crm::CrmToken).to receive(:call).and_return('Token') + allow(service).to receive(:call).and_return(response) + allow_any_instance_of(AskVAApi::Correspondences::Retriever).to receive(:call) + .and_return({ Data: [], + Message: 'Data Validation: No Inquiry Found', + ExceptionOccurred: true, + ExceptionMessage: 'Data Validation: No Inquiry Found', + MessageId: '2d746074-9e5c-4987-a894-e3f834b156b5' }) + end + + it 'returns correspondences as an empty array' do + inquiry = retriever.fetch_by_id(id:) + + expect(inquiry.correspondences).to eq([]) + end + end + + context 'when Correspondence::Retriever returns a success' do + let(:cor_info) do + { + Id: 'f4b12ee3-93bb-ed11-9886-001dd806a6a7', + ModifiedOn: '3/5/2023 8:25:49 PM', + StatusReason: 'Sent', + Description: 'Dear aminul, Thank you for submitting your ' \ + 'Inquiry with the U.S. Department of Veteran Affairs.', + MessageType: 'Notification', + EnableReply: true, + AttachmentNames: nil + } + end + + let(:correspondence) { AskVAApi::Correspondences::Entity.new(cor_info) } + + before do + allow_any_instance_of(Crm::CrmToken).to receive(:call).and_return('Token') + allow(service).to receive(:call).and_return(response) + allow_any_instance_of(AskVAApi::Correspondences::Retriever).to receive(:call) + .and_return([correspondence]) + end + + it 'returns correspondences as an empty array' do + inquiry = retriever.fetch_by_id(id:) + + expect(inquiry.correspondences).to eq([correspondence]) + end + end + end end end end 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 03eec8510ca..1cf3c468603 100644 --- a/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb +++ b/modules/ask_va_api/spec/requests/v0/inquiries_spec.rb @@ -234,7 +234,11 @@ it_behaves_like 'common error handling', :unprocessable_entity, 'service_error', 'AskVAApi::Inquiries::InquiriesRetrieverError: ' \ - 'Data Validation: No Inquiries found by ID A-20240423-30709' + '{:status=>400, :body=>"{\"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\"}",' \ + ' :response_headers=>nil, :url=>nil}' end end end diff --git a/modules/ask_va_api/spec/services/crm/crm_token_spec.rb b/modules/ask_va_api/spec/services/crm/crm_token_spec.rb index c83e5c91b43..ee432210524 100644 --- a/modules/ask_va_api/spec/services/crm/crm_token_spec.rb +++ b/modules/ask_va_api/spec/services/crm/crm_token_spec.rb @@ -30,7 +30,7 @@ def mock_response(status:, body:) end end - context 'with invalid JSON' do + context 'when veis auth service returns a 401 error response' do let(:resp) { mock_response(body: { error: 'invalid_client' }, status: 401) } let(:exception) { Common::Exceptions::BackendServiceException.new(nil, {}, resp.status, resp.body) } diff --git a/modules/ask_va_api/spec/services/crm/service_spec.rb b/modules/ask_va_api/spec/services/crm/service_spec.rb index ba7f2e4dd8b..45269f9a624 100644 --- a/modules/ask_va_api/spec/services/crm/service_spec.rb +++ b/modules/ask_va_api/spec/services/crm/service_spec.rb @@ -5,29 +5,14 @@ RSpec.describe Crm::Service do let(:service) { described_class.new(icn: '123') } - # Helper method to create a mock response def mock_response(status:, body:) instance_double(Faraday::Response, status:, body: body.to_json) end - # Shared examples for error handling - shared_examples 'error handling' do |status, message| - let(:body) { 'Sample error message' } - - it "returns a formatted message for status #{status}" do - response = mock_response(status:, body:) - expected_error_message = "#{message} to #{endpoint}: \"#{body}\"" - - expect do - Crm::ErrorHandler.handle(endpoint, response) - end.to raise_error(Crm::ErrorHandler::ServiceError, expected_error_message) - end - end - describe '#call' do let(:endpoint) { 'inquiries' } - context 'server response' do + context 'when server response successful' do context 'with valid JSON' do let(:response) do mock_response( @@ -64,35 +49,6 @@ def mock_response(status:, body:) end end - describe 'error message formatting' do - context 'when response is nil' do - it 'returns a message indicating no response was received' do - expect do - Crm::ErrorHandler.handle(endpoint, - nil) - end.to raise_error(Crm::ErrorHandler::ServiceError, "Server Error to #{endpoint}: ") - end - end - - context 'with specific response status codes' do - include_examples 'error handling', 400, 'Bad request' - include_examples 'error handling', 401, 'Unauthorized' - include_examples 'error handling', 403, 'Forbidden: You do not have permission to access' - include_examples 'error handling', 404, 'Resource not found' - end - - context 'with unspecified response status codes' do - let(:body) { 'General error message' } - - it 'returns a generic error message' do - response = mock_response(status: 418, body:) - expect do - Crm::ErrorHandler.handle(endpoint, response) - end.to raise_error(Crm::ErrorHandler::ServiceError, "Service Error to #{endpoint}: \"#{body}\"") - end - end - end - context 'when the server returns an error' do let(:resp) { mock_response(body: { error: 'server error' }, status: 500) } let(:exception) { Common::Exceptions::BackendServiceException.new(nil, {}, resp.status, resp.body) }