Skip to content

Commit f2350d2

Browse files
authored
[VI-1104] updates Form526 user_account lookup (#21164)
* updates useraccount lookup * updates * adds MPI call by edipi to Form526 #account * spec updates * removes Account usage from form526 rake task * spec updates * refactoring * restores MPI query by attributes failure log * mpi querying refactor * updates * updates * spex fixes * spec updates * syntax changes
1 parent e6430e0 commit f2350d2

File tree

12 files changed

+221
-160
lines changed

12 files changed

+221
-160
lines changed

app/models/form526_submission.rb

Lines changed: 54 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ class Form526Submission < ApplicationRecord
2323
:submit_flashes,
2424
:poll_form526_pdf,
2525
:cleanup,
26-
additional_class_logs: {
27-
action: 'Begin as anciliary 526 submission'
28-
},
26+
additional_class_logs: { action: 'Begin as anciliary 526 submission' },
2927
additional_instance_logs: {
3028
saved_claim_id: %i[saved_claim id],
3129
user_uuid: %i[user_uuid]
@@ -54,13 +52,11 @@ class Form526Submission < ApplicationRecord
5452
has_kms_key
5553
has_encrypted :auth_headers_json, :birls_ids_tried, :form_json, key: :kms_key, **lockbox_options
5654

57-
belongs_to :saved_claim,
58-
class_name: 'SavedClaim::DisabilityCompensation',
59-
inverse_of: false
55+
belongs_to :saved_claim, class_name: 'SavedClaim::DisabilityCompensation', inverse_of: false
6056

6157
has_many :form526_job_statuses, dependent: :destroy
6258
has_many :form526_submission_remediations, dependent: :destroy
63-
belongs_to :user_account, dependent: nil, optional: true
59+
belongs_to :user_account, dependent: nil
6460

6561
validates(:auth_headers_json, presence: true)
6662
enum :backup_submitted_claim_status, { accepted: 0, rejected: 1, paranoid_success: 2 }
@@ -163,9 +159,7 @@ def submit_with_birls_id_that_hasnt_been_tried_yet!(
163159

164160
# Note that the User record is cached in Redis -- `User.redis_namespace_ttl`
165161
def get_first_name
166-
user = User.find(user_uuid)
167-
user&.first_name&.upcase.presence ||
168-
auth_headers&.dig('va_eauth_firstName')&.upcase
162+
user&.first_name&.upcase.presence || auth_headers&.dig('va_eauth_firstName')&.upcase
169163
end
170164

171165
# Checks against the User record first, and then resorts to checking the auth_headers
@@ -174,15 +168,13 @@ def get_first_name
174168
# @return [Hash] of the user's full name (first, middle, last, suffix)
175169
#
176170
def full_name
177-
name_hash = User.find(user_uuid)&.full_name_normalized
171+
name_hash = user&.full_name_normalized
178172
return name_hash if name_hash&.[](:first).present?
179173

180-
{
181-
first: auth_headers&.dig('va_eauth_firstName')&.capitalize,
174+
{ first: auth_headers&.dig('va_eauth_firstName')&.capitalize,
182175
middle: nil,
183176
last: auth_headers&.dig('va_eauth_lastName')&.capitalize,
184-
suffix: nil
185-
}
177+
suffix: nil }
186178
end
187179

188180
# form_json is memoized here so call invalidate_form_hash after updating form_json
@@ -468,22 +460,11 @@ def last_remediation
468460
end
469461

470462
def account
471-
# first, check for an ICN on the UserAccount associated to the submission, return it if found
472-
account = user_account
473-
return account if account&.icn.present?
474-
475-
# next, check past submissions for different UserAccounts that might have ICNs
476-
past_submissions = get_past_submissions
477-
account = find_user_account_with_icn(past_submissions, 'past submissions')
478-
return account if account.present? && account.icn.present?
479-
480-
# next, check for any historical UserAccounts for that user which might have an ICN
481-
user_verifications = get_user_verifications
482-
account = find_user_account_with_icn(user_verifications, 'user verifications')
483-
return account if account.present? && account.icn.present?
463+
return user_account if user_account&.icn.present?
484464

485-
# failing all the above, default to an Account lookup
486-
Account.lookup_by_user_uuid(user_uuid)
465+
Rails.logger.info('Form526Submission::account - no UserAccount ICN found', log_payload)
466+
# query MPI by EDIPI first & attributes second for user ICN, return in OpenStruct
467+
get_icn_from_mpi
487468
end
488469

489470
# Send the Submitted Email - when the Veteran has clicked the "submit" button in va.gov
@@ -493,8 +474,7 @@ def account
493474
# @param invoker: string where the Received Email trigger is being called from
494475
def send_submitted_email(invoker)
495476
if Flipper.enabled?(:disability_526_send_form526_submitted_email)
496-
Rails.logger.info("Form526SubmittedEmailJob called for user #{user_uuid},
497-
submission: #{id} from #{invoker}")
477+
Rails.logger.info("Form526SubmittedEmailJob called for user #{user_uuid}, submission: #{id} from #{invoker}")
498478
first_name = get_first_name
499479
params = personalization_parameters(first_name)
500480
Form526SubmittedEmailJob.perform_async(params)
@@ -506,8 +486,7 @@ def send_submitted_email(invoker)
506486
# Backup Path: when Form526StatusPollingJob reaches "paranoid_success" status
507487
# @param invoker: string where the Received Email trigger is being called from
508488
def send_received_email(invoker)
509-
Rails.logger.info("Form526ConfirmationEmailJob called for user #{user_uuid},
510-
submission: #{id} from #{invoker}")
489+
Rails.logger.info("Form526ConfirmationEmailJob called for user #{user_uuid}, submission: #{id} from #{invoker}")
511490
first_name = get_first_name
512491
params = personalization_parameters(first_name)
513492
Form526ConfirmationEmailJob.perform_async(params)
@@ -612,7 +591,6 @@ def submit_form_8940
612591
end
613592

614593
def submit_flashes
615-
user = User.find(user_uuid)
616594
# Note that the User record is cached in Redis -- `User.redis_namespace_ttl`
617595
# If this method runs after the TTL, then the flashes will not be applied -- a possible bug.
618596
BGS::FlashUpdater.perform_async(id) if user && Flipper.enabled?(:disability_compensation_flashes, user)
@@ -630,27 +608,51 @@ def cleanup
630608
EVSS::DisabilityCompensationForm::SubmitForm526Cleanup.perform_async(id)
631609
end
632610

633-
def find_user_account_with_icn(records, record_type)
634-
records.pluck(:user_account_id).uniq.each do |user_account_id|
635-
user_account = UserAccount.find(user_account_id)
636-
next if user_account&.icn.blank?
637-
638-
Rails.logger.info("ICN not found on submission #{id}, " \
639-
"using ICN for user account #{user_account_id} instead (based on #{record_type})")
640-
return user_account
611+
def get_icn_from_mpi
612+
edipi_response_profile = edipi_mpi_profile_query(auth_headers['va_eauth_dodedipnid'])
613+
if edipi_response_profile&.icn.present?
614+
OpenStruct.new(icn: edipi_response_profile.icn)
615+
else
616+
Rails.logger.info('Form526Submission::account - unable to look up MPI profile with EDIPI', log_payload)
617+
attributes_response_profile = attributes_mpi_profile_query(auth_headers)
618+
if attributes_response_profile&.icn.present?
619+
OpenStruct.new(icn: attributes_response_profile.icn)
620+
else
621+
Rails.logger.info('Form526Submission::account - no ICN present', log_payload)
622+
OpenStruct.new(icn: nil)
623+
end
641624
end
642625
end
643626

644-
def get_past_submissions
645-
Form526Submission.where(user_uuid:).where.not(user_account_id:)
627+
def edipi_mpi_profile_query(edipi)
628+
return unless edipi
629+
630+
edipi_response = mpi_service.find_profile_by_edipi(edipi:)
631+
edipi_response.profile if edipi_response.ok? && edipi_response.profile.icn.present?
632+
end
633+
634+
def attributes_mpi_profile_query(auth_headers)
635+
required_attributes = %w[va_eauth_firstName va_eauth_lastName va_eauth_birthdate va_eauth_pnid]
636+
return unless required_attributes.all? { |attr| auth_headers[attr].present? }
637+
638+
attributes_response = mpi_service.find_profile_by_attributes(
639+
first_name: auth_headers['va_eauth_firstName'],
640+
last_name: auth_headers['va_eauth_lastName'],
641+
birth_date: auth_headers['va_eauth_birthdate']&.to_date.to_s,
642+
ssn: auth_headers['va_eauth_pnid']
643+
)
644+
attributes_response.profile if attributes_response.ok? && attributes_response.profile.icn.present?
645+
end
646+
647+
def log_payload
648+
@log_payload ||= { user_uuid:, submission_id: id }
649+
end
650+
651+
def mpi_service
652+
@mpi_service ||= MPI::Service.new
646653
end
647654

648-
def get_user_verifications
649-
UserVerification.where(idme_uuid: user_uuid)
650-
.or(UserVerification.where(backing_idme_uuid: user_uuid))
651-
.or(UserVerification.where(logingov_uuid: user_uuid))
652-
.or(UserVerification.where(mhv_uuid: user_uuid))
653-
.or(UserVerification.where(dslogon_uuid: user_uuid))
654-
.where.not(user_account_id:)
655+
def user
656+
@user ||= User.find(user_uuid)
655657
end
656658
end

rakelib/form526.rake

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -518,11 +518,15 @@ namespace :form526 do
518518
end
519519

520520
vname = "#{fs.auth_headers['va_eauth_firstName']} #{fs.auth_headers['va_eauth_lastName']}"
521-
icn = Account.lookup_by_user_uuid(fs.user_uuid).first&.icn
521+
icn = fs.user_account&.icn
522522
if icn.blank?
523-
# TODO: make this work for blank icn's
524-
puts "icn blank #{fs.id}"
525-
next
523+
mpi_response = MPI::Service.new.find_profile_by_edipi(edipi: fs['va_eauth_dodedipnid'])
524+
if mpi_response.ok? && mpi_response.profile.icn.present?
525+
icn = mpi_response.profile.icn
526+
else
527+
puts "icn blank #{fs.id}"
528+
next
529+
end
526530
end
527531
user = OpenStruct.new(participant_id: fs.auth_headers['va_eauth_pid'], icn:, common_name: vname,
528532
ssn:)
@@ -684,42 +688,26 @@ namespace :form526 do
684688
desc 'pretty print MPI profile for submission'
685689
task mpi: :environment do |_, args|
686690
def puts_mpi_profile(submission)
687-
ids = {}
688-
ids[:edipi] = edipi submission.auth_headers
689-
ids[:icn] = icn ids[:edipi]
691+
edipi = submission.auth_headers['va_eauth_dodedipnid']
692+
raise Error, 'no edipi' unless edipi
690693

691-
pp mpi_profile(user_identity(**ids)).as_json
694+
ids = { edipi:, icn: submission.user_account&.icn }
695+
696+
pp mpi_profile(ids).as_json
692697
end
693698

694-
def mpi_profile(user_identity)
695-
if user_identity.mhv_icn
696-
find_profile_response = MPI::Service.new.find_profile_by_identifier(identifier: user_identity.mhv_icn,
699+
def mpi_profile(ids)
700+
if ids[:icn]
701+
find_profile_response = MPI::Service.new.find_profile_by_identifier(identifier: ids[:icn],
697702
identifier_type: MPI::Constants::ICN)
698703
else
699-
find_profile_response = MPI::Service.new.find_profile_by_edipi(edipi: user_identity.edipi)
704+
find_profile_response = MPI::Service.new.find_profile_by_edipi(edipi: ids[:edipi])
700705
end
701706
raise find_profile_response.error if find_profile_response.error
702707

703708
find_profile_response.profile
704709
end
705710

706-
def user_identity(icn:, edipi:)
707-
OpenStruct.new mhv_icn: icn, edipi:
708-
end
709-
710-
def edipi(auth_headers)
711-
auth_headers['va_eauth_dodedipnid']
712-
end
713-
714-
def icn(edipi)
715-
raise Error, 'no edipi' unless edipi
716-
717-
icns = Account.where(edipi:).pluck :icn
718-
raise Error, 'multiple icns' if icns.uniq.length > 1
719-
720-
icns.first
721-
end
722-
723711
Form526Submission.where(id: args.extras).find_each { |sub| puts_mpi_profile sub }
724712
end
725713

spec/factories/form526_submissions.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
FactoryBot.define do
44
factory :form526_submission do
55
transient do
6-
user { create(:disabilities_compensation_user) }
6+
user_verification { create(:idme_user_verification) }
7+
user { create(:disabilities_compensation_user, idme_uuid: user_verification.idme_uuid) }
78
submissions_path { Rails.root.join(*'/spec/support/disability_compensation_form/submissions'.split('/')).to_s }
89
end
10+
user_account { user_verification.user_account }
911
user_uuid { user.uuid }
1012
saved_claim { create(:va526ez) }
1113
submitted_claim_id { nil }

spec/lib/sidekiq/form526_backup_submission_process/processor_spec.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@
2828
end
2929

3030
describe '#choose_provider' do
31-
let(:account) { create(:account) }
32-
let(:submission) { create(:form526_submission, user_uuid: account.idme_uuid, submit_endpoint: 'claims_api') }
31+
let(:user) { create(:user, :loa3, :with_terms_of_use_agreement) }
32+
let(:user_account) { user.user_account }
33+
let(:icn) { user_account.icn }
34+
let(:submission) { create(:form526_submission, user_account:, submit_endpoint: 'claims_api') }
3335

3436
it 'delegates to the ApiProviderFactory with the correct data' do
3537
auth_headers = {}
@@ -38,7 +40,7 @@
3840
type: ApiProviderFactory::FACTORIES[:generate_pdf],
3941
provider: ApiProviderFactory::API_PROVIDER[:lighthouse],
4042
options: { auth_headers:, breakered: true },
41-
current_user: OpenStruct.new({ flipper_id: submission.user_uuid, icn: account.icn }),
43+
current_user: OpenStruct.new({ flipper_id: submission.user_uuid, icn: }),
4244
feature_toggle: nil
4345
}
4446
)
@@ -59,7 +61,7 @@
5961
type: ApiProviderFactory::FACTORIES[:generate_pdf],
6062
provider: ApiProviderFactory::API_PROVIDER[:lighthouse],
6163
options: { auth_headers: submission.auth_headers, breakered: true },
62-
current_user: OpenStruct.new({ flipper_id: submission.user_uuid, icn: account.icn }),
64+
current_user: OpenStruct.new({ flipper_id: submission.user_uuid, icn: }),
6365
feature_toggle: nil
6466
}
6567
).and_call_original

spec/lib/sidekiq/form526_backup_submission_process/submit_spec.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
.and_return('access_token')
1717
end
1818

19-
let(:user) { create(:user, :loa3) }
19+
let(:user_account) { create(:user_account, icn: '123498767V234859') }
20+
let(:user) { create(:user, :loa3, icn: user_account.icn) }
2021
let(:auth_headers) do
2122
EVSS::DisabilityCompensationAuthHeaders.new(user).add_headers(EVSS::AuthHeaders.new(user).to_h)
2223
end
@@ -27,7 +28,7 @@
2728
allow(Settings.form526_backup).to receive(:enabled).and_return(false)
2829
end
2930

30-
let!(:submission) { create(:form526_submission, :with_everything) }
31+
let!(:submission) { create(:form526_submission, :with_everything, user_account:) }
3132

3233
it 'creates a submission job' do
3334
expect { subject.perform_async(submission.id) }.to change(subject.jobs, :size).by(1)
@@ -42,7 +43,7 @@
4243
let(:timestamp) { Time.now.utc }
4344

4445
context 'when all retries are exhausted' do
45-
let!(:form526_submission) { create(:form526_submission) }
46+
let!(:form526_submission) { create(:form526_submission, user_account:) }
4647
let!(:form526_job_status) { create(:form526_job_status, :retryable_error, form526_submission:, job_id: 1) }
4748

4849
it 'updates a StatsD counter and updates the status on an exhaustion event' do
@@ -111,7 +112,7 @@
111112
allow(Settings.form526_backup).to receive_messages(submission_method: payload_method, enabled: true)
112113
end
113114

114-
let!(:submission) { create(:form526_submission, :with_everything) }
115+
let!(:submission) { create(:form526_submission, :with_everything, user_account:) }
115116
let!(:upload_data) { submission.form[Form526Submission::FORM_526_UPLOADS] }
116117

117118
context 'successfully' do
@@ -222,7 +223,7 @@
222223
allow(Settings.form526_backup).to receive_messages(submission_method: 'single', enabled: true)
223224
end
224225

225-
let!(:submission) { create(:form526_submission, :with_non_pdf_uploads) }
226+
let!(:submission) { create(:form526_submission, :with_non_pdf_uploads, user_account:) }
226227
let!(:upload_data) { submission.form[Form526Submission::FORM_526_UPLOADS] }
227228

228229
context 'converts non-pdf files to pdf' do

spec/lib/sidekiq/form526_job_status_tracker/job_tracker_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
end
1919

2020
context 'with an exhausted callback message' do
21-
let!(:form526_submission) { create(:form526_submission) }
21+
let(:user_account) { create(:user_account, icn: '123498767V234859') }
22+
let!(:form526_submission) { create(:form526_submission, user_account:) }
2223
let!(:form526_job_status) do
2324
create(:form526_job_status, job_id: msg['jid'], form526_submission:)
2425
end

0 commit comments

Comments
 (0)