Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
52a160d
email job
svalexander Oct 26, 2022
3f8fec7
moving email job file and fixing missing end
svalexander Oct 27, 2022
8db4ad5
send partially working
svalexander Oct 27, 2022
66b08e9
email job working
svalexander Oct 28, 2022
d536f5e
include test for needs email reminder
svalexander Oct 28, 2022
c0154ef
add test for excluded enrollments
svalexander Oct 28, 2022
0710531
make methods private
svalexander Oct 31, 2022
aa49e4f
fall back to app name if sp_name is not available
svalexander Oct 31, 2022
8e00e96
changelog:Improvement, Job, add email reminder job
svalexander Oct 31, 2022
954080e
db migration
svalexander Nov 1, 2022
0899ca0
update email reminder so it covers a range of dates
svalexander Nov 1, 2022
ad5c6a2
can be equal to end interval
svalexander Nov 1, 2022
bf98edd
adjust interval
svalexander Nov 3, 2022
cfd6bfc
update config names
svalexander Nov 3, 2022
f449be2
make input param names clearer and change time to make sure correct d…
svalexander Nov 3, 2022
10d2f19
update email reminder tests
svalexander Nov 3, 2022
7d2def4
lint fix
svalexander Nov 3, 2022
b00584a
update calculation so excludes enrollments on late benchmark and incl…
svalexander Nov 4, 2022
66b107d
fix test so correct enrollments are picked based on established_at time
svalexander Nov 4, 2022
2d83d45
fix lint issue
svalexander Nov 4, 2022
867f059
check flags are false and remove unneeded test
svalexander Nov 4, 2022
1625881
move email reminder job to in person folder
svalexander Nov 7, 2022
68cfd92
Merge branch 'main' into shannon/lg-7185-email-reminders-job-new
svalexander Nov 7, 2022
fa69523
fix lint
svalexander Nov 7, 2022
a22443a
job spec
svalexander Nov 8, 2022
36794ea
continued work on job spec
svalexander Nov 9, 2022
33bd16b
check enrollment code
svalexander Nov 9, 2022
fb93206
update to email job
svalexander Nov 9, 2022
d9e1190
some tests pass and others fail
svalexander Nov 10, 2022
d97c606
tests working and lint changes
svalexander Nov 14, 2022
406031d
update naming
svalexander Nov 14, 2022
a4fe8dd
refactor based on feedback
svalexander Nov 16, 2022
9ca2b5a
update tests
svalexander Nov 16, 2022
8a3e5b3
remove unneeded nil check
svalexander Nov 16, 2022
959ba8d
Merge remote-tracking branch 'origin/main' into shannon/lg-7185-email…
Nov 16, 2022
d805490
LG-7185: Add error handling and analytics to in-person proofing email…
Nov 21, 2022
d244335
Merge remote-tracking branch 'origin/main' into shannon/lg-7185-email…
Nov 21, 2022
5841d1f
Merge remote-tracking branch 'origin/main' into shannon/lg-7185-email…
Nov 22, 2022
14783a4
pluralize email subject and header by days left
Nov 23, 2022
f231d34
Merge remote-tracking branch 'origin/main' into shannon/lg-7185-email…
Nov 23, 2022
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
95 changes: 95 additions & 0 deletions app/jobs/in_person/email_reminder_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# frozen_string_literal: true
Copy link
Copy Markdown
Contributor

@lizzieamanning lizzieamanning Nov 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good! starting a thread here arbitrarily for small design comments @tomas-nava

  1. Can we shift which text we are linking in the bottom of the box outlining items to bring from "Questions about what to bring? Learn more" to "Questions? Learn more about what to bring." (indicating what text should be linked here with bold). Also linking this design that accurately reflects what I mean. I also believe our link style uses an underline, if we could add that here.
  2. Are we able to add more space between the sentence "You can see any associate at the retail window to verify your identity" and "Your deadline to verify your identity in person is..." at the bottom of the email to more accurately reflect the design above as well?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created LG-8207 to track this work


module InPerson
Comment thread
svalexander marked this conversation as resolved.
class EmailReminderJob < ApplicationJob
EMAIL_TYPE_EARLY = 'early'
EMAIL_TYPE_LATE = 'late'

queue_as :low

include GoodJob::ActiveJobExtensions::Concurrency

Comment thread
svalexander marked this conversation as resolved.
good_job_control_concurrency_with(
total_limit: 1,
key: 'in_person_email_reminder_job',
)

discard_on GoodJob::ActiveJobExtensions::Concurrency::ConcurrencyExceededError

def perform(_now)
Comment thread
svalexander marked this conversation as resolved.
return true unless IdentityConfig.store.in_person_proofing_enabled

# send late emails first in case of job failure
late_enrollments = InPersonEnrollment.needs_late_email_reminder(
late_benchmark,
final_benchmark,
)
send_emails_for_enrollments(enrollments: late_enrollments, email_type: EMAIL_TYPE_LATE)

early_enrollments = InPersonEnrollment.needs_early_email_reminder(
early_benchmark,
late_benchmark,
)
send_emails_for_enrollments(enrollments: early_enrollments, email_type: EMAIL_TYPE_EARLY)
end

private

def analytics(user: AnonymousUser.new)
Analytics.new(user: user, request: nil, session: {}, sp: nil)
end

def send_emails_for_enrollments(enrollments:, email_type:)
enrollments.each do |enrollment|
send_reminder_email(enrollment.user, enrollment)
rescue StandardError => err
NewRelic::Agent.notice_error(err)
analytics(user: enrollment.user).idv_in_person_email_reminder_job_exception(
enrollment_id: enrollment.id,
exception_class: err.class.to_s,
exception_message: err.message,
)
else
analytics(user: enrollment.user).idv_in_person_email_reminder_job_email_initiated(
email_type: email_type,
enrollment_id: enrollment.id,
)
if email_type == EMAIL_TYPE_EARLY
enrollment.update!(early_reminder_sent: true)
elsif email_type == EMAIL_TYPE_LATE
enrollment.update!(late_reminder_sent: true)
end
end
end

def calculate_interval(benchmark)
days_until_expired = IdentityConfig.store.in_person_enrollment_validity_in_days.days
(Time.zone.now - days_until_expired) + benchmark.days
end

def early_benchmark
calculate_interval(IdentityConfig.store.in_person_email_reminder_early_benchmark_in_days)
end

def late_benchmark
calculate_interval(IdentityConfig.store.in_person_email_reminder_late_benchmark_in_days)
end

def final_benchmark
calculate_interval(IdentityConfig.store.in_person_email_reminder_final_benchmark_in_days)
end

def send_reminder_email(user, enrollment)
user.confirmed_email_addresses.each do |email_address|
# rubocop:disable IdentityIdp/MailLaterLinter
UserMailer.with(
user: user,
email_address: email_address,
).in_person_ready_to_verify_reminder(
enrollment: enrollment,
).deliver_later
# rubocop:enable IdentityIdp/MailLaterLinter
end
end
end
end
4 changes: 2 additions & 2 deletions app/mailers/user_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -295,13 +295,13 @@ def in_person_ready_to_verify_reminder(enrollment:)
)
@header = t(
'user_mailer.in_person_ready_to_verify_reminder.heading',
days_remaining: @presenter.days_remaining,
count: @presenter.days_remaining,
)
mail(
to: email_address.email,
subject: t(
'user_mailer.in_person_ready_to_verify_reminder.subject',
days_remaining: @presenter.days_remaining,
count: @presenter.days_remaining,
),
)
end
Expand Down
22 changes: 22 additions & 0 deletions app/models/in_person_enrollment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@ class InPersonEnrollment < ApplicationRecord
before_save(:on_status_updated, if: :will_save_change_to_status?)
before_create(:set_unique_id, unless: :unique_id)

def self.is_pending_and_established_between(early_benchmark, late_benchmark)
where(status: :pending).
and(
where(enrollment_established_at: late_benchmark...(early_benchmark.end_of_day)),
).
order(enrollment_established_at: :asc)
end

def self.needs_early_email_reminder(early_benchmark, late_benchmark)
self.is_pending_and_established_between(
early_benchmark,
late_benchmark,
).where(early_reminder_sent: false)
end

def self.needs_late_email_reminder(early_benchmark, late_benchmark)
self.is_pending_and_established_between(
early_benchmark,
late_benchmark,
).where(late_reminder_sent: false)
end

# Find enrollments that need a status check via the USPS API
def self.needs_usps_status_check(check_interval)
where(status: :pending).
Expand Down
2 changes: 1 addition & 1 deletion app/presenters/idv/in_person/ready_to_verify_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def service_provider
end

def sp_name
service_provider ? service_provider.friendly_name : ''
service_provider ? service_provider.friendly_name : APP_NAME
end

private
Expand Down
35 changes: 35 additions & 0 deletions app/services/analytics_events.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3094,6 +3094,25 @@ def idv_in_person_usps_proofing_results_job_exception(
)
end

# Tracks exceptions that are raised when running InPerson::EmailReminderJob
# @param [String] enrollment_id
# @param [String] exception_class
# @param [String] exception_message
def idv_in_person_email_reminder_job_exception(
enrollment_id:,
exception_class: nil,
exception_message: nil,
**extra
)
track_event(
'InPerson::EmailReminderJob: Exception raised when attempting to send reminder email',
enrollment_id: enrollment_id,
exception_class: exception_class,
exception_message: exception_message,
**extra,
)
end

# Tracks individual enrollments that are updated during GetUspsProofingResultsJob
# @param [String] enrollment_code
# @param [String] enrollment_id
Expand Down Expand Up @@ -3132,6 +3151,22 @@ def idv_in_person_usps_proofing_results_job_email_initiated(
)
end

# Tracks emails that are initiated during InPerson::EmailReminderJob
# @param [String] email_type early or late
# @param [String] enrollment_id
def idv_in_person_email_reminder_job_email_initiated(
email_type:,
enrollment_id:,
**extra
)
track_event(
'InPerson::EmailReminderJob: Reminder email initiated',
email_type: email_type,
enrollment_id: enrollment_id,
**extra,
)
end

# Tracks users visiting the recovery options page
def account_reset_recovery_options_visit
track_event('Account Reset: Recovery Options Visited')
Expand Down
3 changes: 3 additions & 0 deletions config/application.yml.default
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ idv_send_link_attempt_window_in_minutes: 10
idv_send_link_max_attempts: 5
ie11_support_end_date: '2022-12-31'
idv_sp_required: false
in_person_email_reminder_early_benchmark_in_days: 11
in_person_email_reminder_final_benchmark_in_days: 1
in_person_email_reminder_late_benchmark_in_days: 4
in_person_proofing_enabled: false
in_person_enrollment_validity_in_days: 30
in_person_results_delay_in_hours: 1
Expand Down
6 changes: 6 additions & 0 deletions config/initializers/job_configurations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@
cron: IdentityConfig.store.get_usps_proofing_results_job_cron,
args: -> { [Time.zone.now] },
},
# Queue daily in-person proofing reminder email job
email_reminder_job: {
class: 'InPerson::EmailReminderJob',
cron: cron_24h,
args: -> { [Time.zone.today] },
},
# Periodically verify signature on ThreatMetrix javascript
verify_threat_metrix_js: {
class: 'ThreatMetrixJsVerificationJob',
Expand Down
8 changes: 6 additions & 2 deletions config/locales/user_mailer/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,14 @@ en:
subject: You’re ready to verify your identity with %{app_name} in person
in_person_ready_to_verify_reminder:
greeting: Hello,
heading: You have %{days_remaining} days left to verify your identity in person
heading:
one: You have %{count} day left to verify your identity in person
other: You have %{count} days left to verify your identity in person
intro: Don’t miss the chance to verify your identity at your local Post Office.
Complete this step to access %{sp_name}.
subject: Verify your identity at a Post Office in the next %{days_remaining} days
subject:
one: Verify your identity at a Post Office in the next day
other: Verify your identity at a Post Office in the next %{count} days
in_person_verified:
greeting: Hello,
intro: You successfully verified your identity at the %{location} Post Office on
Expand Down
10 changes: 7 additions & 3 deletions config/locales/user_mailer/es.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,15 @@ es:
subject: Está listo para verificar su identidad con %{app_name} en persona
in_person_ready_to_verify_reminder:
greeting: Hola,
heading: Tiene %{days_remaining} días para verificar su identidad en persona
heading:
one: Tiene %{count} día para verificar su identidad en persona
other: Tiene %{count} días para verificar su identidad en persona
intro: No pierda la oportunidad de verificar su identidad en su oficina de
correos local. Complete este paso para acceder %{sp_name}.
subject: Verifique su identidad en una oficina de correos en los próximos
%{days_remaining} días
subject:
one: Verifique su identidad en una oficina de correos en el próximo día
other: Verifique su identidad en una oficina de correos en los próximos %{count}
días
in_person_verified:
greeting: Hola,
intro: El %{date}, verificó correctamente su identidad en la oficina de correos
Expand Down
11 changes: 7 additions & 4 deletions config/locales/user_mailer/fr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,15 @@ fr:
subject: Vous êtes prêt à vérifier votre identité avec %{app_name} en personne
in_person_ready_to_verify_reminder:
greeting: Bonjour,
heading: Il vous reste %{days_remaining} jours pour vérifier votre identité en
personne
heading:
one: Il vous reste %{count} jour pour vérifier votre identité en personne
other: Il vous reste %{count} jours pour vérifier votre identité en personne
intro: Ne manquez pas l’occasion de vérifier votre identité dans votre bureau de
poste de proximité. Complétez cette étape pour accéder à %{sp_name}.
subject: Vérifiez votre identité auprès d’un bureau de poste dans les
%{days_remaining} prochains jours.
subject:
one: Vérifiez votre identité auprès d’un bureau de poste dans le prochain jour
other: Vérifiez votre identité auprès d’un bureau de poste dans les %{count}
prochains jours
in_person_verified:
greeting: Bonjour,
intro: Vous avez vérifié avec succès votre identité au bureau de poste de
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class AddEarlyReminderSentAndLateReminderSentToInPersonEnrollments < ActiveRecord::Migration[7.0]
def change
add_column :in_person_enrollments, :early_reminder_sent, :boolean, default: false, comment: "early reminder to complete IPP before deadline sent"
add_column :in_person_enrollments, :late_reminder_sent, :boolean, default: false, comment: "late reminder to complete IPP before deadline sent"
end
end
2 changes: 2 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@
t.datetime "enrollment_established_at", comment: "When the enrollment was successfully established"
t.string "issuer", comment: "Issuer associated with the enrollment at time of creation"
t.boolean "follow_up_survey_sent", default: false
t.boolean "early_reminder_sent", default: false, comment: "early reminder to complete IPP before deadline sent"
t.boolean "late_reminder_sent", default: false, comment: "late reminder to complete IPP before deadline sent"
t.index ["profile_id"], name: "index_in_person_enrollments_on_profile_id"
t.index ["unique_id"], name: "index_in_person_enrollments_on_unique_id", unique: true
t.index ["user_id", "status"], name: "index_in_person_enrollments_on_user_id_and_status", unique: true, where: "(status = 1)"
Expand Down
3 changes: 3 additions & 0 deletions lib/identity_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ def self.build_store(config_map)
config.add(:idv_send_link_max_attempts, type: :integer)
config.add(:idv_sp_required, type: :boolean)
config.add(:ie11_support_end_date, type: :timestamp)
config.add(:in_person_email_reminder_early_benchmark_in_days, type: :integer)
config.add(:in_person_email_reminder_final_benchmark_in_days, type: :integer)
config.add(:in_person_email_reminder_late_benchmark_in_days, type: :integer)
config.add(:in_person_proofing_enabled, type: :boolean)
config.add(:in_person_enrollment_validity_in_days, type: :integer)
config.add(:in_person_results_delay_in_hours, type: :integer)
Expand Down
Loading