Skip to content

Commit

Permalink
Add a count of remaining messages to the 80% warning emails (#1971)
Browse files Browse the repository at this point in the history
* Add a count of remaining messages to the 80% warning emails

* Bump some migration numbers

- There is another PR in the pipeline that adds some migrations. Bumping these ones to avoid collisions

* Add french translations

* formatting

* Fix incorrectly encoded characters

* Added missing bolding

* Add current sent count to emails

- Fixed contact us links, and links to 'times across canada' site
- Added missing fields to personalisation in send_near_email_limit_email and send_near_sms_limit_email

* fix tests

* fix: bug where email limit was being used instead of sms limit

---------

Co-authored-by: Andrew Leith <[email protected]>
  • Loading branch information
whabanks and andrewleith authored Sep 18, 2023
1 parent 2b9d512 commit ac442f3
Show file tree
Hide file tree
Showing 5 changed files with 224 additions and 6 deletions.
19 changes: 15 additions & 4 deletions app/notifications/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def send_warning_email_limit_emails_if_needed(service: Service) -> None:
if bool_nearing_email_daily_limit:
cache_key = near_email_daily_limit_cache_key(service.id)
if not redis_store.get(cache_key):
send_near_email_limit_email(service)
send_near_email_limit_email(service, todays_current_email_count)
redis_store.set(cache_key, current_time, ex=cache_expiration)

# Send a warning when reaching the daily message limit
Expand All @@ -198,7 +198,7 @@ def send_warning_sms_limit_emails_if_needed(service: Service):
if nearing_sms_daily_limit:
cache_key = near_sms_daily_limit_cache_key(service.id)
if not redis_store.get(cache_key):
send_near_sms_limit_email(service)
send_near_sms_limit_email(service, todays_requested_sms)
redis_store.set(cache_key, current_time, ex=cache_expiration)

# Send a warning when reaching the daily message limit
Expand Down Expand Up @@ -257,6 +257,7 @@ def warn_about_daily_message_limit(service: Service, messages_sent):
template_id=current_app.config["NEAR_DAILY_LIMIT_TEMPLATE_ID"],
personalisation={
"service_name": service.name,
"count": messages_sent,
"contact_url": f"{current_app.config['ADMIN_BASE_URL']}/contact",
"message_limit_en": "{:,}".format(service.message_limit),
"message_limit_fr": "{:,}".format(service.message_limit).replace(",", " "),
Expand Down Expand Up @@ -293,14 +294,19 @@ def warn_about_daily_message_limit(service: Service, messages_sent):
raise LiveServiceTooManyRequestsError(service.message_limit)


def send_near_sms_limit_email(service: Service):
def send_near_sms_limit_email(service: Service, sms_sent):
limit_reset_time_et = get_limit_reset_time_et()
sms_remaining = service.sms_daily_limit - sms_sent
send_notification_to_service_users(
service_id=service.id,
template_id=current_app.config["NEAR_DAILY_SMS_LIMIT_TEMPLATE_ID"],
personalisation={
"service_name": service.name,
"contact_url": f"{current_app.config['ADMIN_BASE_URL']}/contact",
"count_en": "{:,}".format(sms_sent),
"count_fr": "{:,}".format(sms_sent).replace(",", " "),
"remaining_en": "{:,}".format(sms_remaining),
"remaining_fr": "{:,}".format(sms_remaining).replace(",", " "),
"message_limit_en": "{:,}".format(service.sms_daily_limit),
"message_limit_fr": "{:,}".format(service.sms_daily_limit).replace(",", " "),
"limit_reset_time_et_12hr": limit_reset_time_et["12hr"],
Expand All @@ -311,18 +317,23 @@ def send_near_sms_limit_email(service: Service):
current_app.logger.info(f"service {service.id} is approaching its daily sms limit of {service.sms_daily_limit}")


def send_near_email_limit_email(service: Service) -> None:
def send_near_email_limit_email(service: Service, emails_sent) -> None:
"""
Send an email to service users when nearing the daily email limit.
"""
limit_reset_time_et = get_limit_reset_time_et()
emails_remaining = service.message_limit - emails_sent
send_notification_to_service_users(
service_id=service.id,
template_id=current_app.config["NEAR_DAILY_EMAIL_LIMIT_TEMPLATE_ID"],
personalisation={
"service_name": service.name,
"contact_url": f"{current_app.config['ADMIN_BASE_URL']}/contact",
"count_en": "{:,}".format(emails_sent),
"count_fr": "{:,}".format(emails_sent).replace(",", " "),
"remaining_en": "{:,}".format(emails_remaining),
"remaining_fr": "{:,}".format(emails_remaining).replace(",", " "),
"message_limit_en": "{:,}".format(service.message_limit),
"message_limit_fr": "{:,}".format(service.message_limit).replace(",", " "),
"limit_reset_time_et_12hr": limit_reset_time_et["12hr"],
Expand Down
2 changes: 1 addition & 1 deletion migrations/versions/0434_update_email_templates_sms.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"",
"Bonjour ((name)),",
"",
"((service_name)) peut envoyer ((message_limit_fr)) messages texte par jour. Si vous atteignez cette limite avant ((limit_reset_time_et_24hr)) heures, heure de l’Est, vos envois seront bloqués. Comparez [les heures officielles au Canada](https://nrc.canada.ca/fr/horloge-web/).",
"((service_name)) peut envoyer ((message_limit_fr)) messages texte par jour. Si vous atteignez cette limite avant ((limit_reset_time_et_24hr)) heures, heure de l’Est, vos envois seront bloqués. Comparez [les heures officielles au Canada](https://nrc.canada.ca/fr/horloge-web/).",
"",
"Veuillez [nous contacter](((contact_url))) si vous désirez augmenter votre limite d’envoi. Nous vous répondrons en un jour ouvrable.",
"",
Expand Down
101 changes: 101 additions & 0 deletions migrations/versions/0437_email_templates_msgs_left.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
"""
Revision ID: 0437_email_templates_msgs_left
Revises: 0436_add_columns_api_keys
Create Date: 2023-10-05 00:00:00
"""
from datetime import datetime

from alembic import op
from flask import current_app

revision = "0437_email_templates_msgs_left"
down_revision = "0436_add_columns_api_keys"

near_content = "\n".join(
[
"(la version française suit)",
"",
"Hello ((name)),",
"",
"((service_name)) has sent ((count_en)) out of its limit of ((message_limit_en)) emails per 24 hours.",
"",
"**((service_name)) can send ((remaining_en)) more messages until your limit resets at ((limit_reset_time_et_12hr)) Eastern Time.** Compare official times across Canada](https://nrc.canada.ca/en/web-clock/).",
"",
"To request a limit increase, [contact us](((contact_url))). We’ll respond within 1 business day.",
"",
"The GC Notify team",
"",
"---",
"",
"Bonjour ((name)),",
"",
"((service_name)) a envoyé ((count_fr)) courriels de sa limite de ((message_limit_fr)) courriels par 24 heures.",
"",
"**((service_name)) peut encore envoyer ((remaining_fr)) messages d’ici à ce que votre limite de courriels soit réinitialisée à ((limit_reset_time_et_24hr)), heure de l’Est.** Comparez les heures officielles à travers le Canada.",
"",
"Pour demander une augmentation de votre limite, [veuillez nous joindre](((contact_url))). Nous vous répondrons en un jour ouvrable.",
"",
"L’équipe Notification GC",
]
)

templates = [
{
"id": current_app.config["NEAR_DAILY_EMAIL_LIMIT_TEMPLATE_ID"],
"name": "Near daily EMAIL limit",
"template_type": "email",
"content": near_content,
"subject": "((service_name)) is near its daily limit for emails. | La limite quotidienne d’envoi de courriels est presque atteinte pour ((service_name)).",
"process_type": "priority",
},
]


def upgrade():
conn = op.get_bind()

for template in templates:
current_version = conn.execute("select version from templates where id='{}'".format(template["id"])).fetchone()
template["version"] = current_version[0] + 1

template_update = """
UPDATE templates SET content = '{}', subject = '{}', version = '{}', updated_at = '{}'
WHERE id = '{}'
"""
template_history_insert = """
INSERT INTO templates_history (id, name, template_type, created_at, content, archived, service_id, subject,
created_by_id, version, process_type, hidden)
VALUES ('{}', '{}', '{}', '{}', '{}', False, '{}', '{}', '{}', {}, '{}', false)
"""

for template in templates:
op.execute(
template_update.format(
template["content"],
template["subject"],
template["version"],
datetime.utcnow(),
template["id"],
)
)

op.execute(
template_history_insert.format(
template["id"],
template["name"],
template["template_type"],
datetime.utcnow(),
template["content"],
current_app.config["NOTIFY_SERVICE_ID"],
template["subject"],
current_app.config["NOTIFY_USER_ID"],
template["version"],
template["process_type"],
)
)


def downgrade():
pass
102 changes: 102 additions & 0 deletions migrations/versions/0438_sms_templates_msgs_left.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""
Revision ID: 0438_sms_templates_msgs_left
Revises: 0437_email_templates_msgs_left
Create Date: 2023-10-05 00:00:00
"""
from datetime import datetime

from alembic import op
from flask import current_app

revision = "0438_sms_templates_msgs_left"
down_revision = "0437_email_templates_msgs_left"

near_content = "\n".join(
[
"(la version française suit)",
"",
"Hello ((name)),",
"",
"((service_name)) has sent ((count_en)) out of its limit of ((message_limit_en)) text messages per 24 hours.",
"",
"**((service_name)) can send ((remaining_en)) more messages until your limit resets at ((limit_reset_time_et_12hr)) Eastern Time.** Compare [official times across Canada](https://nrc.canada.ca/en/web-clock/).",
"",
"To request a limit increase, [contact us](((contact_url))). We’ll respond within 1 business day.",
"",
"The GC Notify team",
"---",
"",
"Bonjour ((name)),",
"",
"((service_name)) a envoyé ((count_fr)) messages de sa limite de ((message_limit_fr)) messages texte par 24 heures.",
"",
"**((service_name)) peut encore envoyer ((remaining_fr)) messages d’ici à ce que votre limite de messages texte soit réinitialisée à ((limit_reset_time_et_24hr)), heure de l’Est.** Comparez les [heures officielles à travers le Canada](https://nrc.canada.ca/en/web-clock/).",
"",
"Pour demander une augmentation de votre limite, [veuillez nous joindre](((contact_url))). Nous vous répondrons en un jour ouvrable.",
"",
"L’équipe Notification GC",
]
)


templates = [
{
"id": current_app.config["NEAR_DAILY_SMS_LIMIT_TEMPLATE_ID"],
"template_type": "email",
"subject": "((service_name)) is near its daily limit for text messages. | La limite quotidienne d’envoi de messages texte est presque atteinte pour ((service_name)).",
"content": near_content,
"process_type": "priority",
},
]


def upgrade():
conn = op.get_bind()

for template in templates:
current_version = conn.execute("select version from templates where id='{}'".format(template["id"])).fetchone()
name = conn.execute("select name from templates where id='{}'".format(template["id"])).fetchone()
template["version"] = current_version[0] + 1
template["name"] = name[0]

template_update = """
UPDATE templates SET content = '{}', subject = '{}', version = '{}', updated_at = '{}'
WHERE id = '{}'
"""
template_history_insert = """
INSERT INTO templates_history (id, name, template_type, created_at, content, archived, service_id, subject,
created_by_id, version, process_type, hidden)
VALUES ('{}', '{}', '{}', '{}', '{}', False, '{}', '{}', '{}', {}, '{}', false)
"""

for template in templates:
op.execute(
template_update.format(
template["content"],
template["subject"],
template["version"],
datetime.utcnow(),
template["id"],
)
)

op.execute(
template_history_insert.format(
template["id"],
template["name"],
template["template_type"],
datetime.utcnow(),
template["content"],
current_app.config["NOTIFY_SERVICE_ID"],
template["subject"],
current_app.config["NOTIFY_USER_ID"],
template["version"],
template["process_type"],
)
)


def downgrade():
pass
6 changes: 5 additions & 1 deletion tests/app/notifications/test_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ def test_check_service_message_limit_records_nearing_daily_limit(

service = create_sample_service(notify_db, notify_db_session, restricted=True, limit=5, sms_limit=5)
template = create_sample_template(notify_db, notify_db_session, service=service, template_type=limit_type)
for x in range(4):
for x in range(5):
create_sample_notification(notify_db, notify_db_session, service=service, template=template)

if limit_type == "sms":
Expand All @@ -232,6 +232,10 @@ def test_check_service_message_limit_records_nearing_daily_limit(
personalisation={
"service_name": service.name,
"contact_url": f"{current_app.config['ADMIN_BASE_URL']}/contact",
"count_en": "4",
"count_fr": "4",
"remaining_en": "1",
"remaining_fr": "1",
"message_limit_en": "5",
"message_limit_fr": "5",
**kwargs,
Expand Down

0 comments on commit ac442f3

Please sign in to comment.