Class: DecisionReview::FailureNotificationEmailJob

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Job
Defined in:
app/sidekiq/decision_review/failure_notification_email_job.rb

Constant Summary collapse

SAVED_CLAIM_MODEL_TYPES =
%w[
  SavedClaim::NoticeOfDisagreement
  SavedClaim::HigherLevelReview
  SavedClaim::SupplementalClaim
].freeze
ERROR_STATUS =
'error'
STATSD_KEY_PREFIX =
'worker.decision_review.failure_notification_email'

Instance Method Summary collapse

Instance Method Details

#enabled?Boolean (private)

Returns:

  • (Boolean)


230
231
232
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 230

def enabled?
  Flipper.enabled? :decision_review_failure_notification_email_job_enabled
end

#errored_saved_claimsObject (private)

Fetches SavedClaim records for DecisionReview that have an error status for the form or any evidence attachments



53
54
55
56
57
58
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 53

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

#errored_secondary_formsObject (private)



76
77
78
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 76

def errored_secondary_forms
  @errored_secondary_forms ||= SecondaryAppealForm.needs_failure_notification.order(id: :asc)
end

#performObject



22
23
24
25
26
27
28
29
30
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 22

def perform
  return unless should_perform?

  send_form_emails
  send_evidence_emails
  send_secondary_form_emails if secondary_forms_enabled?

  nil
end

#perform_allObject (private)



42
43
44
45
46
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 42

def perform_all
  enabled? &&
    (secondary_forms_enabled? &&
    (submissions.present? || submission_uploads.present? || errored_secondary_forms.present?))
end

#perform_form_and_evidenceObject (private)



38
39
40
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 38

def perform_form_and_evidence
  enabled? && (submissions.present? || submission_uploads.present?)
end

#record_evidence_email_send_failure(upload, e) ⇒ Object (private)



213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 213

def record_evidence_email_send_failure(upload, e)
  submission = upload.appeal_submission
  appeal_type = submission.type_of_appeal
  params = {
    submitted_appeal_uuid: submission.,
    lighthouse_upload_id: upload.lighthouse_upload_id,
    appeal_type:,
    message: e.message
  }
  Rails.logger.error('DecisionReview::FailureNotificationEmailJob evidence error', params)
  StatsD.increment("#{STATSD_KEY_PREFIX}.evidence.error", tags: ["appeal_type:#{appeal_type}"])

  tags = ["service:#{DecisionReviewV1::APPEAL_TYPE_TO_SERVICE_MAP[appeal_type]}",
          'function: evidence submission to Lighthouse']
  StatsD.increment('silent_failure', tags:)
end

#record_evidence_email_send_successful(upload, notification_id) ⇒ Object (private)



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 196

def record_evidence_email_send_successful(upload, notification_id)
  submission = upload.appeal_submission
  appeal_type = submission.type_of_appeal
  params = {
    submitted_appeal_uuid: submission.,
    lighthouse_upload_id: upload.lighthouse_upload_id,
    appeal_type:,
    notification_id:
  }
  Rails.logger.info('DecisionReview::FailureNotificationEmailJob evidence email queued', params)
  StatsD.increment("#{STATSD_KEY_PREFIX}.evidence.email_queued", tags: ["appeal_type:#{appeal_type}"])

  tags = ["service:#{DecisionReviewV1::APPEAL_TYPE_TO_SERVICE_MAP[appeal_type]}",
          'function: evidence submission to Lighthouse']
  StatsD.increment('silent_failure_avoided_no_confirmation', tags:)
end

#record_form_email_send_failure(submission, e) ⇒ Object (private)



155
156
157
158
159
160
161
162
163
164
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 155

def record_form_email_send_failure(submission, e)
  appeal_type = submission.type_of_appeal
  params = { submitted_appeal_uuid: submission., appeal_type:, message: e.message }
  Rails.logger.error('DecisionReview::FailureNotificationEmailJob form error', params)
  StatsD.increment("#{STATSD_KEY_PREFIX}.form.error", tags: ["appeal_type:#{appeal_type}"])

  tags = ["service:#{DecisionReviewV1::APPEAL_TYPE_TO_SERVICE_MAP[appeal_type]}",
          'function: form submission to Lighthouse']
  StatsD.increment('silent_failure', tags:)
end

#record_form_email_send_successful(submission, notification_id) ⇒ Object (private)



144
145
146
147
148
149
150
151
152
153
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 144

def record_form_email_send_successful(submission, notification_id)
  appeal_type = submission.type_of_appeal
  params = { submitted_appeal_uuid: submission., appeal_type:, notification_id: }
  Rails.logger.info('DecisionReview::FailureNotificationEmailJob form email queued', params)
  StatsD.increment("#{STATSD_KEY_PREFIX}.form.email_queued", tags: ["appeal_type:#{appeal_type}"])

  tags = ["service:#{DecisionReviewV1::APPEAL_TYPE_TO_SERVICE_MAP[appeal_type]}",
          'function: form submission to Lighthouse']
  StatsD.increment('silent_failure_avoided_no_confirmation', tags:)
end

#record_secondary_form_email_send_failure(secondary_form, e) ⇒ Object (private)



181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 181

def record_secondary_form_email_send_failure(secondary_form, e)
  submission = secondary_form.appeal_submission
  appeal_type = submission.type_of_appeal
  params = { submitted_appeal_uuid: submission.,
             lighthouse_upload_id: secondary_form.guid,
             appeal_type:,
             message: e.message }
  Rails.logger.error('DecisionReview::FailureNotificationEmailJob secondary form error', params)
  StatsD.increment("#{STATSD_KEY_PREFIX}.secondary_form.error", tags: ["appeal_type:#{appeal_type}"])

  tags = ["service:#{DecisionReviewV1::APPEAL_TYPE_TO_SERVICE_MAP[appeal_type]}",
          'function: secondary form submission to Lighthouse']
  StatsD.increment('silent_failure', tags:)
end

#record_secondary_form_email_send_successful(secondary_form, notification_id) ⇒ Object (private)



166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 166

def record_secondary_form_email_send_successful(secondary_form, notification_id)
  submission = secondary_form.appeal_submission
  appeal_type = submission.type_of_appeal
  params = { submitted_appeal_uuid: submission.,
             lighthouse_upload_id: secondary_form.guid,
             appeal_type:,
             notification_id: }
  Rails.logger.info('DecisionReview::FailureNotificationEmailJob secondary form email queued', params)
  StatsD.increment("#{STATSD_KEY_PREFIX}.secondary_form.email_queued", tags: ["appeal_type:#{appeal_type}"])

  tags = ["service:#{DecisionReviewV1::APPEAL_TYPE_TO_SERVICE_MAP[appeal_type]}",
          'function: secondary form submission to Lighthouse']
  StatsD.increment('silent_failure_avoided_no_confirmation', tags:)
end

#secondary_forms_enabled?Boolean (private)

Returns:

  • (Boolean)


234
235
236
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 234

def secondary_forms_enabled?
  Flipper.enabled? :decision_review_notify_4142_failures
end

#send_email_with_vanotify(submission, filename, created_at, template_id, reference) ⇒ Object (private)



80
81
82
83
84
85
86
87
88
89
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 80

def send_email_with_vanotify(submission, filename, created_at, template_id, reference)
  email_address = submission.current_email_address
  personalisation = {
    first_name: submission.get_mpi_profile.given_names[0],
    filename:,
    date_submitted: created_at.strftime('%B %d, %Y')
  }

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

#send_evidence_emailsObject (private)



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 108

def send_evidence_emails
  StatsD.increment("#{STATSD_KEY_PREFIX}.evidence.processing_records", submission_uploads.size)

  submission_uploads.each do |upload|
    submission = upload.appeal_submission
    appeal_type = submission.type_of_appeal
    reference = "#{appeal_type}-evidence-#{upload.lighthouse_upload_id}"

    response = send_email_with_vanotify(submission, upload.masked_attachment_filename, upload.created_at,
                                        DecisionReviewV1::EVIDENCE_TEMPLATE_IDS[appeal_type], reference)
    upload.update(failure_notification_sent_at: DateTime.now)

    record_evidence_email_send_successful(upload, response.id)
  rescue => e
    record_evidence_email_send_failure(upload, e)
  end
end

#send_form_emailsObject (private)



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 91

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

  submissions.each do |submission|
    appeal_type = submission.type_of_appeal
    reference = "#{appeal_type}-form-#{submission.}"

    response = send_email_with_vanotify(submission, nil, submission.created_at,
                                        DecisionReviewV1::FORM_TEMPLATE_IDS[appeal_type], reference)
    submission.update(failure_notification_sent_at: DateTime.now)

    record_form_email_send_successful(submission, response.id)
  rescue => e
    record_form_email_send_failure(submission, e)
  end
end

#send_secondary_form_emailsObject (private)



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 126

def send_secondary_form_emails
  StatsD.increment("#{STATSD_KEY_PREFIX}.secondary_forms.processing_records", errored_secondary_forms.size)
  errored_secondary_forms.each do |form|
    appeal_type = form.appeal_submission.type_of_appeal
    reference = "#{appeal_type}-secondary_form-#{form.guid}"
    response = send_email_with_vanotify(form.appeal_submission,
                                        nil,
                                        form.created_at,
                                        DecisionReviewV1::SECONDARY_FORM_TEMPLATE_ID,
                                        reference)
    form.update(failure_notification_sent_at: DateTime.now)

    record_secondary_form_email_send_successful(form, response.id)
  rescue => e
    record_secondary_form_email_send_failure(form, e)
  end
end

#should_perform?Boolean (private)

Returns:

  • (Boolean)


34
35
36
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 34

def should_perform?
  perform_form_and_evidence || perform_all
end

#submission_uploadsObject (private)



67
68
69
70
71
72
73
74
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 67

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

    ::AppealSubmissionUpload.where(lighthouse_upload_id: ids).failure_not_sent
  end
end

#submissionsObject (private)



60
61
62
63
64
65
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 60

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

#vanotify_serviceObject (private)



48
49
50
# File 'app/sidekiq/decision_review/failure_notification_email_job.rb', line 48

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