Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor FailureNotificationEmailJob #18881

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions app/models/appeal_submission.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

has_many :appeal_submission_uploads, dependent: :destroy

scope :failure_not_sent, -> { where(failure_notification_sent_at: nil).order(id: :asc) }

def self.submit_nod(request_body_hash:, current_user:, decision_review_service: nil)
ActiveRecord::Base.transaction do
raise 'Must pass in a version of the DecisionReview Service' if decision_review_service.nil?
Expand Down Expand Up @@ -52,4 +54,26 @@
DecisionReview::SubmitUpload.perform_async(asu.id)
end
end

def current_email
va_profile = ::VAProfile::ContactInformation::Service.get_person(mpi_profile.vet360_id.to_s)&.person
raise 'Failed to fetch VA profile' if va_profile.nil?

current_emails = va_profile.emails.select { |email| email.effective_end_date.nil? }
current_emails.first&.email_address || raise('Failed to retrieve email')
end

def mpi_profile
mpi_profile = get_mpi_profile(user_uuid)

Check failure on line 67 in app/models/appeal_submission.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Lint/UselessAssignment: Useless assignment to variable - `mpi_profile`. Did you mean `idme_profile`?

service = ::MPI::Service.new

idme = service.find_profile_by_identifier(identifier: user_uuid, identifier_type: 'idme')

Check failure on line 71 in app/models/appeal_submission.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Lint/UselessAssignment: Useless assignment to variable - `idme`.
logingov = service.find_profile_by_identifier(identifier: user_uuid, identifier_type: 'logingov')

Check failure on line 72 in app/models/appeal_submission.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Lint/UselessAssignment: Useless assignment to variable - `logingov`.

response = idme_profile || logingov_profile
raise 'Failed to fetch MPI profile' if response.nil?

response&.profile
end
end
9 changes: 9 additions & 0 deletions app/models/appeal_submission_upload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,13 @@ class AppealSubmissionUpload < ApplicationRecord
foreign_key: 'guid',
class_name: 'DecisionReviewEvidenceAttachment',
inverse_of: :appeal_submission_upload, dependent: :nullify

scope :failure_not_sent, -> { where(failure_notification_sent_at: nil).order(id: :asc) }

def attachment_filename
form_attachment = FormAttachment.find_by(guid: decision_review_evidence_attachment_guid)
raise "FormAttachment guid='#{guid}' not found" if form_attachment.nil?

JSON.parse(form_attachment.file_data)['filename'].gsub(/(?<=.{3})[^_-](?=.{6})/, '*')
end
end
137 changes: 137 additions & 0 deletions app/sidekiq/decision_review/failure_notification_email_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# frozen_string_literal: true

require 'sidekiq'

module DecisionReview
class FailureNotificationEmailJob
include Sidekiq::Job

sidekiq_options retry: false, unique_for: 30.minutes

SAVED_CLAIM_MODEL_TYPES = %w[
SavedClaim::NoticeOfDisagreement
SavedClaim::HigherLevelReview
SavedClaim::SupplementalClaim
].freeze

TEMPLATE_IDS = {
'HLR' => Settings.vanotify.services.benefits_decision_review.template_id.higher_level_review_form_error_email,
'NOD' => Settings.vanotify.services.benefits_decision_review.template_id.notice_of_disagreement_form_error_email,
'SC' => Settings.vanotify.services.benefits_decision_review.template_id.supplemental_claim_form_error_email
}.freeze

ERROR_STATUS = 'error'

STATSD_KEY_PREFIX = 'worker.decision_review.failure_notification_email'

def perform
return unless enabled? && (submissions.present? || submission_uploads.present?)

send_form_emails
send_evidence_emails

nil
end

private

def send_form_emails
StatsD.increment("#{STATSD_KEY_PREFIX}.form.processing_records", submissions.size)
submissions.each do |submission|

Check failure on line 41 in app/sidekiq/decision_review/failure_notification_email_job.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Layout/EmptyLinesAroundBlockBody: Extra empty line detected at block body beginning.
send_email_with_vanotify(submission, nil, submission.created_at)

submission.update(failure_notification_sent_at: DateTime.now)
record_successful_form_email_sent(submission)
rescue => e
record_failure_form_email_sent(submission, e)
end
end

def send_evidence_emails
StatsD.increment("#{STATSD_KEY_PREFIX}.evidence.processing_records", submission_uploads.size)
submission_uploads.each do |upload|
submission = upload.appeal_submission

send_email_with_vanotify(submission, upload.attachment_filename, upload.created_at)

upload.update(failure_notification_sent_at: DateTime.now)

record_successful_evidence_email_sent(submission)
rescue => e
record_failure_evidence_email_sent(upload, e)
end
end

def send_email_with_vanotify(submission, filename, created_at)
email_address = submission.current_email
personalisation = {
first_name: submission.mpi_profile.given_names[0],
filename: filename,

Check failure on line 70 in app/sidekiq/decision_review/failure_notification_email_job.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Style/HashSyntax: Omit the hash value.
date_submitted: created_at.strftime('%B %d, %Y')
}
template_id = TEMPLATE_IDS[submission.type_of_appeal]

vanotify_service.send_email({ email_address:, template_id:, personalisation: })
end

def vanotify_service
@service ||= ::VaNotify::Service.new(Settings.vanotify.services.benefits_decision_review.api_key)
end

def errored_saved_claims
@errored_saved_claims ||= ::SavedClaim.where(type: SAVED_CLAIM_MODEL_TYPES).where(delete_date: nil)
.where('metadata LIKE ?', '%error%')
.order(id: :asc)
end

def submissions
@submissions ||= begin
uuids = errored_saved_claims.select { |sc| JSON.parse(sc.metadata)['status'] == ERROR_STATUS }.pluck(:guid)
::AppealSubmission.where(submitted_appeal_uuid: uuids).failure_not_sent
end
end

def submission_uploads
@submission_uploads ||= begin
uploads = errored_saved_claims.map { |sc| JSON.parse(sc.metadata)['uploads'] }
ids = uploads.flatten.select { |upload| upload&.fetch('status') == ERROR_STATUS }.pluck('id')
::AppealSubmissionUpload.where(lighthouse_upload_id: ids).failure_not_sent
end
end

def enabled?
Flipper.enabled? :decision_review_failure_notification_email_job_enabled
end

def record_successful_form_email_sent(submission)
metadata = { submission_uuid: submission.submitted_appeal_uuid, form_type: submission.type_of_appeal }
Rails.logger.info('DecisionReview::FailureNotificationEmailJob form email sent', metadata)

StatsD.increment("#{STATSD_KEY_PREFIX}.form.email_queued", tags: ["form_type:#{submission.type_of_appeal}"])
end

def record_failure_form_email_sent(submission, error)
metadata = { submission_uuid: submission.submitted_appeal_uuid, message: error.message }
Rails.logger.error('DecisionReview::FailureNotificationEmailJob form error', metadata)

StatsD.increment("#{STATSD_KEY_PREFIX}.form.error", tags: ["form_type:#{submission.type_of_appeal}"])
end

def record_successful_evidence_email_sent(submission)
metadata = { submission_uuid: submission.submitted_appeal_uuid, form_type: submission.type_of_appeal }
Rails.logger.info('DecisionReview::FailureNotificationEmailJob evidence email sent', metadata)
StatsD.increment("#{STATSD_KEY_PREFIX}.evidence.email_queued", tags: ["form_type:#{submission.type_of_appeal}"])
end

def record_failure_evidence_email_sent(upload, error)
submission = upload.appeal_submission
submission_uuid = submission.submitted_appeal_uuid

metadata = { lighthouse_upload_id: upload.lighthouse_upload_id, submission_uuid: , message: error.message }

Check failure on line 131 in app/sidekiq/decision_review/failure_notification_email_job.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Lint/UselessAssignment: Useless assignment to variable - `metadata`.

Check failure on line 131 in app/sidekiq/decision_review/failure_notification_email_job.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Layout/SpaceBeforeComma: Space found before comma.
Rails.logger.error('DecisionReview::FailureNotificationEmailJob evidence error',

Check failure on line 132 in app/sidekiq/decision_review/failure_notification_email_job.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Style/TrailingCommaInArguments: Avoid comma after the last parameter of a method call.
)

Check failure on line 133 in app/sidekiq/decision_review/failure_notification_email_job.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Layout/ClosingParenthesisIndentation: Align `)` with `(`.

Check failure on line 133 in app/sidekiq/decision_review/failure_notification_email_job.rb

View workflow job for this annotation

GitHub Actions / Linting and Security

Layout/MultilineMethodCallBraceLayout: Closing method call brace must be on the same line as the last argument when opening brace is on the same line as the first argument.
StatsD.increment("#{STATSD_KEY_PREFIX}.evidence.error", tags: ["form_type:#{submission.type_of_appeal}"])
end
end
end
Loading