-
Notifications
You must be signed in to change notification settings - Fork 167
LG-7185 email reminders #7198
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
LG-7185 email reminders #7198
Changes from all commits
bdef9b4
5d2a695
8e3762b
cb4b59d
d26dbf7
d589e77
7edc39c
45a44ad
2020506
1f4e906
46fde8d
921b3c8
b7f890e
77bcd73
740e76e
cfcd2a1
1ff5290
6732692
a2640c4
b9d2513
1107866
aee55c7
7bfb0e0
31e9165
5a7357b
e47c997
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -65,6 +65,16 @@ def self.generate_unique_id | |||||||||||||||||
| SecureRandom.hex(9) | ||||||||||||||||||
| end | ||||||||||||||||||
|
|
||||||||||||||||||
| def due_date | ||||||||||||||||||
| start_date = enrollment_established_at.presence || created_at | ||||||||||||||||||
| start_date + IdentityConfig.store.in_person_enrollment_validity_in_days.days | ||||||||||||||||||
| end | ||||||||||||||||||
|
Comment on lines
+68
to
+71
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this would be misleading for enrollments that have status
Suggested change
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we were using created_at here to account for some enrollments that only have created_at defined when the enrollment status changes to pending and the user becomes ready to verify. We want to default to created_at if there's no enrollment_established_at value. (ticket)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. An enrollment doesn't have a due date until it's pending though. If we use the It's not a hill I want to die on but I am curious why we defined it that way in the ticket, I'm going to ask the ticket creator
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm fine with removing the fallback to
I don't think we have to be too rigorous about protecting against this case though, because when we write the job, we shouldn't be generating emails for non-pending enrollments, which means we should never be in the circumstance where we're getting a nil value for due date. |
||||||||||||||||||
|
|
||||||||||||||||||
| def days_to_due_date | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, non-blocking suggestion
Suggested change
|
||||||||||||||||||
| today = DateTime.now | ||||||||||||||||||
| (today...due_date).count | ||||||||||||||||||
| end | ||||||||||||||||||
|
|
||||||||||||||||||
| private | ||||||||||||||||||
|
|
||||||||||||||||||
| def on_status_updated | ||||||||||||||||||
|
|
||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -8,13 +8,20 @@ class ReadyToVerifyPresenter | |||||
|
|
||||||
| delegate :selected_location_details, :enrollment_code, to: :enrollment | ||||||
|
|
||||||
| def initialize(enrollment:, barcode_image_url: nil) | ||||||
| def initialize(enrollment:, barcode_image_url: nil, sp_name: nil) | ||||||
| @enrollment = enrollment | ||||||
| @barcode_image_url = barcode_image_url | ||||||
| @sp_name = sp_name | ||||||
| end | ||||||
|
|
||||||
| # Reminder is exclusive of the day the email is sent (1 less than days_to_due_date) | ||||||
| def days_remaining | ||||||
| enrollment.days_to_due_date - 1 | ||||||
| end | ||||||
|
|
||||||
| def formatted_due_date | ||||||
| due_date.in_time_zone(USPS_SERVER_TIMEZONE).strftime(I18n.t('time.formats.event_date')) | ||||||
| enrollment.due_date.in_time_zone(USPS_SERVER_TIMEZONE). | ||||||
| strftime(I18n.t('time.formats.event_date')) | ||||||
| end | ||||||
|
|
||||||
| def selected_location_hours(prefix) | ||||||
|
|
@@ -27,15 +34,18 @@ def needs_proof_of_address? | |||||
| !enrollment.current_address_matches_id | ||||||
| end | ||||||
|
|
||||||
| def service_provider | ||||||
| enrollment.service_provider | ||||||
| end | ||||||
|
|
||||||
| def sp_name | ||||||
| service_provider ? service_provider.friendly_name : '' | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a question about what should happen if there is no service provider. We'll see that a lot in lower environments today. And after we finish the pilot I think there will be ways for production users to get into the IPP flow without an associated partner, such as by going through the password reset flow I left a question on the Figma file about it
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that's a good question. i left it as an empty string and so in examples i looked at w/o one it looks like an unfinished sentence -it definitely is not ideal. would be good to adjust for sure.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lizzie suggested we discuss it at design critique on Monday so I'm going to plan to attend for that. Do you want to join too?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We discussed during design critique and tentatively agreed to fall back to
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is being addressed in #7256 |
||||||
| end | ||||||
|
|
||||||
| private | ||||||
|
|
||||||
| attr_reader :enrollment | ||||||
|
|
||||||
| def due_date | ||||||
| start_date = enrollment.enrollment_established_at.presence || enrollment.created_at | ||||||
| start_date + IdentityConfig.store.in_person_enrollment_validity_in_days.days | ||||||
| end | ||||||
|
|
||||||
svalexander marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| def localized_hours(hours) | ||||||
| case hours | ||||||
| when 'Closed' | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| <p> | ||
svalexander marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| <%= t('user_mailer.in_person_ready_to_verify_reminder.greeting') %><br> | ||
| <%= t('user_mailer.in_person_ready_to_verify_reminder.intro', sp_name: @presenter.sp_name) %> | ||
| </p> | ||
|
|
||
| <%= render 'user_mailer/shared/in_person_ready_to_verify' %> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| <table class="info-alert margin-y-4"> | ||
| <tr> | ||
| <td width="16"> | ||
| <%= image_tag('email/info.png', width: 16, height: 16, alt: '') %> | ||
| </td> | ||
| <td> | ||
| <p class="margin-bottom-1"><strong><%= t('in_person_proofing.body.barcode.deadline', deadline: @presenter.formatted_due_date) %></strong></p> | ||
| <p class="margin-bottom-0"><%= t('in_person_proofing.body.barcode.deadline_restart') %></p> | ||
| </td> | ||
| </tr> | ||
| </table> | ||
|
|
||
| <div class="border-1px border-primary-light radius-lg padding-4"> | ||
| <h2 class="margin-top-0 margin-bottom-2 font-heading-lg text-bold"> | ||
| <%= t('in_person_proofing.body.barcode.items_to_bring') %> | ||
| </h2> | ||
| <table class="process-list"> | ||
| <tr> | ||
| <td><div class="process-list__circle">1</div></td> | ||
| <td> | ||
| <h3 class="font-heading-md text-bold"><%= t('in_person_proofing.process.barcode.heading') %></h3> | ||
| <p><%= t('in_person_proofing.process.barcode.info') %></p> | ||
| <%= render BarcodeComponent.new( | ||
| barcode_data: @presenter.enrollment_code, | ||
| barcode_image_url: @presenter.barcode_image_url, | ||
| label: nil, | ||
| label_formatter: Idv::InPerson::EnrollmentCodeFormatter.method(:format), | ||
| ) %> | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td><div class="process-list__circle">2</div></td> | ||
| <td> | ||
| <h3 class="font-heading-md text-bold"><%= t('in_person_proofing.process.state_id.heading') %></h3> | ||
| <p class="margin-bottom-105"><%= t('in_person_proofing.process.state_id.info') %></p> | ||
| <ul class="usa-list margin-y-105"> | ||
| <% t('in_person_proofing.process.state_id.acceptable_documents').each do |document| %> | ||
| <li><%= document %></li> | ||
| <% end %> | ||
| </ul> | ||
| <p><%= t('in_person_proofing.process.state_id.no_other_documents') %></p> | ||
| </td> | ||
| </tr> | ||
| <% if @presenter.needs_proof_of_address? %> | ||
| <tr> | ||
| <td><div class="process-list__circle">3</div></td> | ||
| <td> | ||
| <h3 class="font-heading-md text-bold"><%= t('in_person_proofing.process.proof_of_address.heading') %></h3> | ||
| <p class="margin-bottom-105"><%= t('in_person_proofing.process.proof_of_address.info') %></p> | ||
| <ul class="usa-list margin-y-105"> | ||
| <% t('in_person_proofing.process.proof_of_address.acceptable_proof').each do |proof| %> | ||
| <li><%= proof %></li> | ||
| <% end %> | ||
| </ul> | ||
| <p><%= t('in_person_proofing.process.proof_of_address.physical_or_digital_copy') %></p> | ||
| </td> | ||
| </tr> | ||
| <% end %> | ||
| </table> | ||
| <p class="margin-bottom-0"> | ||
| <%= t('in_person_proofing.body.barcode.items_to_bring_questions') %> | ||
| <%= link_to( | ||
| t('in_person_proofing.body.barcode.learn_more'), | ||
| MarketingSite.help_center_article_url( | ||
| category: 'verify-your-identity', | ||
| article: 'verify-your-identity-in-person', | ||
| ), | ||
| ) %> | ||
| </p> | ||
| </div> | ||
|
|
||
| <% if @presenter.selected_location_details.present? %> | ||
| <div class="margin-y-4"> | ||
| <h2 class="font-sans-md margin-bottom-1 text-normal text-bold"><%= @presenter.selected_location_details['name'] %></h2> | ||
| <div class="margin-bottom-1"> | ||
| <%= @presenter.selected_location_details['street_address'] %><br> | ||
| <%= @presenter.selected_location_details['formatted_city_state_zip'] %> | ||
| </div> | ||
| <div><strong><%= t('in_person_proofing.body.barcode.retail_hours') %></strong></div> | ||
| <div class="margin-bottom-2"> | ||
| <%= t('date.range', from: t('date.day_names')[0], to: t('date.day_names')[4]) %>: <%= @presenter.selected_location_hours(:weekday) %><br> | ||
| <%= t('date.day_names')[5] %>: <%= @presenter.selected_location_hours(:saturday) %><br> | ||
| <%= t('date.day_names')[6] %>: <%= @presenter.selected_location_hours(:sunday) %> | ||
| </div> | ||
| <div> | ||
| <%= @presenter.selected_location_details[:phone] %> | ||
| </div> | ||
| </div> | ||
| <% end %> | ||
|
|
||
| <p><%= t('in_person_proofing.body.barcode.speak_to_associate') %></p> | ||
|
|
||
| <p> | ||
| <strong><%= t('in_person_proofing.body.barcode.deadline', deadline: @presenter.formatted_due_date) %></strong> | ||
| <%= t('in_person_proofing.body.barcode.no_appointment_required') %> | ||
| </p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is non-blocking, it's kind of beyond the scope of this ticket. But I feel like
expiration_dateis a slightly better name, it better describes what the consequence of this date is and relates to theexpiredstatus of enrollments. Would require updating a few other places in the code to make this change cohesive though 🤷