-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: validate annual limit * fix: modify wrapper to work with older redis keys * test: add tests! * chore: `utcnow` is deprecated, use `now` instead * feat(annual limits): show error if user is over annual limits * fix: move daily limit message into the appropriate template * feat: add a client to get daily/yearly sent stats using caching where possible * add translations * chore: formatting * fix send to work without FF too * feat: fix sending; write tests; 🙏 * fix: only check for `send_exceeds_annual_limit` when FF is on * fix(tests): only run the new tests with the FF on (they cant pass with it off!) * chore: remove unused imports * fix: move secondary message outside banner * fix: undo ruff change made by accident --------- Co-authored-by: William B <[email protected]>
- Loading branch information
1 parent
8ffc649
commit d3887e5
Showing
12 changed files
with
526 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
from notifications_utils.clients.redis import ( | ||
email_daily_count_cache_key, | ||
sms_daily_count_cache_key, | ||
) | ||
|
||
from app import redis_client, service_api_client, template_statistics_client | ||
|
||
|
||
class NotificationCounts: | ||
def get_all_notification_counts_for_today(self, service_id): | ||
# try to get today's stats from redis | ||
todays_sms = redis_client.get(sms_daily_count_cache_key(service_id)) | ||
todays_email = redis_client.get(email_daily_count_cache_key(service_id)) | ||
|
||
if todays_sms is not None and todays_email is not None: | ||
return {"sms": todays_sms, "email": todays_email} | ||
# fallback to the API if the stats are not in redis | ||
else: | ||
stats = template_statistics_client.get_template_statistics_for_service(service_id, limit_days=1) | ||
transformed_stats = _aggregate_notifications_stats(stats) | ||
|
||
return transformed_stats | ||
|
||
def get_all_notification_counts_for_year(self, service_id, year): | ||
""" | ||
Get total number of notifications by type for the current service for the current year | ||
Return value: | ||
{ | ||
'sms': int, | ||
'email': int | ||
} | ||
""" | ||
stats_today = self.get_all_notification_counts_for_today(service_id) | ||
stats_this_year = service_api_client.get_monthly_notification_stats(service_id, year)["data"] | ||
stats_this_year = _aggregate_stats_from_service_api(stats_this_year) | ||
# aggregate stats_today and stats_this_year | ||
for template_type in ["sms", "email"]: | ||
stats_this_year[template_type] += stats_today[template_type] | ||
|
||
return stats_this_year | ||
|
||
|
||
# TODO: consolidate this function and other functions that transform the results of template_statistics_client calls | ||
def _aggregate_notifications_stats(template_statistics): | ||
template_statistics = _filter_out_cancelled_stats(template_statistics) | ||
notifications = {"sms": 0, "email": 0} | ||
for stat in template_statistics: | ||
notifications[stat["template_type"]] += stat["count"] | ||
|
||
return notifications | ||
|
||
|
||
def _filter_out_cancelled_stats(template_statistics): | ||
return [s for s in template_statistics if s["status"] != "cancelled"] | ||
|
||
|
||
def _aggregate_stats_from_service_api(stats): | ||
"""Aggregate monthly notification stats excluding cancelled""" | ||
total_stats = {"sms": {}, "email": {}} | ||
|
||
for month_data in stats.values(): | ||
for msg_type in ["sms", "email"]: | ||
if msg_type in month_data: | ||
for status, count in month_data[msg_type].items(): | ||
if status != "cancelled": | ||
if status not in total_stats[msg_type]: | ||
total_stats[msg_type][status] = 0 | ||
total_stats[msg_type][status] += count | ||
|
||
return {msg_type: sum(counts.values()) for msg_type, counts in total_stats.items()} | ||
|
||
|
||
notification_counts_client = NotificationCounts() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,29 @@ | ||
{% from "components/banner.html" import banner_wrapper %} | ||
{% from "components/links.html" import content_link %} | ||
|
||
<p> | ||
{%- if current_service.trial_mode %} | ||
{{ _("Your service is in trial mode. To send more messages, <a href='{}'>request to go live</a>").format(url_for('main.request_to_go_live', service_id=current_service.id)) }} | ||
{% else %} | ||
{{ _("To request a daily limit above {} emails, {}").format(current_service.message_limit, content_link(_("contact us"), url_for('main.contact'), is_external_link=true)) }} | ||
{% if send_exceeds_annual_limit %} | ||
|
||
<p data-testid="exceeds-annual">{{ _('<strong>{}</strong> can only send <strong>{}</strong> more email messages until annual limit resets'.format(current_service.name, recipients_remaining_messages)) }}</p> | ||
<p> | ||
{{ _('To send some of these messages now, edit the spreadsheet to <strong>{}</strong> recipients maximum. '.format(recipients_remaining_messages)) }} | ||
{{ _('To send to recipients you removed, wait until <strong>April 1, {}</strong> or contact them some other way.'.format(now().year)) }} | ||
</p> | ||
|
||
{% elif send_exceeds_daily_limit or recipients.more_rows_than_can_send %} | ||
{% call banner_wrapper(type='dangerous') %} | ||
{{ _("To request a daily limit above {} emails, {}").format(current_service.message_limit, content_link(_("contact us"), url_for('main.contact'), is_external_link=true)) }} | ||
{% endcall %} | ||
|
||
<h2 class="heading-medium">{{ _('You cannot send all these email messages today') }}</h2> | ||
<p data-testid="exceeds-daily"> | ||
{{ _("You can try sending these messages after {} Eastern Time. Check {}.").format(time_to_reset[current_lang], | ||
content_link(_("your current local time"), _('https://nrc.canada.ca/en/web-clock/'), is_external_link=true))}} | ||
</p> | ||
{% endif %} | ||
|
||
{%- endif -%} | ||
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.