diff --git a/app/__init__.py b/app/__init__.py
index 590f0f595..c108d6a8c 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -311,6 +311,26 @@ def init_app(application):
def _nav_selected():
return navigation
+ @application.context_processor
+ def _attach_current_daily_remaining_messages_per_service():
+ remaining_messages = 0
+
+ if hasattr(current_service, 'message_limit'):
+ remaining_messages = current_service.message_limit - service_api_client.get_notification_count(
+ service_id=current_service.id)
+
+ return {'daily_remaining_messages': remaining_messages}
+
+ @application.context_processor
+ def _attach_current_global_daily_messages():
+ remaining_global_messages = 0
+
+ if current_app:
+ global_limit = current_app.config['GLOBAL_SERVICE_MESSAGE_LIMIT']
+ global_messages_count = service_api_client.get_global_notification_count()
+ remaining_global_messages = global_limit - global_messages_count
+ return {'daily_global_messages_remaining': remaining_global_messages}
+
@application.before_request
def record_start_time():
g.start = monotonic()
diff --git a/app/config.py b/app/config.py
index c6b5c5791..b204c229a 100644
--- a/app/config.py
+++ b/app/config.py
@@ -47,6 +47,8 @@ class Config(object):
DEFAULT_SERVICE_LIMIT = 50
+ GLOBAL_SERVICE_MESSAGE_LIMIT = 5000
+
EMAIL_EXPIRY_SECONDS = 3600 # 1 hour
INVITATION_EXPIRY_SECONDS = 3600 * 24 * 2 # 2 days - also set on api
EMAIL_2FA_EXPIRY_SECONDS = 1800 # 30 Minutes
diff --git a/app/main/views/send.py b/app/main/views/send.py
index 764b3daee..b96479d58 100644
--- a/app/main/views/send.py
+++ b/app/main/views/send.py
@@ -80,6 +80,9 @@ def get_example_csv_rows(template, use_example_as_example=True, submitted_fields
@main.route("/services//send//csv", methods=['GET', 'POST'])
@user_has_permissions('send_messages', restrict_admin_usage=True)
def send_messages(service_id, template_id):
+ notification_count = service_api_client.get_notification_count(service_id)
+ remaining_messages = current_service.message_limit - notification_count
+
db_template = current_service.get_template_with_user_permission_or_403(template_id, current_user)
email_reply_to = None
@@ -154,7 +157,8 @@ def send_messages(service_id, template_id):
column_headings=list(ascii_uppercase[:len(column_headings)]),
example=[column_headings, get_example_csv_rows(template)],
form=form,
- allowed_file_extensions=Spreadsheet.ALLOWED_FILE_EXTENSIONS
+ allowed_file_extensions=Spreadsheet.ALLOWED_FILE_EXTENSIONS,
+ remaining_messages=remaining_messages
)
diff --git a/app/notify_client/service_api_client.py b/app/notify_client/service_api_client.py
index 449a5e4b0..8c55d5157 100644
--- a/app/notify_client/service_api_client.py
+++ b/app/notify_client/service_api_client.py
@@ -1,6 +1,9 @@
from datetime import datetime
-from notifications_utils.clients.redis import daily_limit_cache_key
+from notifications_utils.clients.redis import (
+ daily_limit_cache_key,
+ daily_total_cache_key,
+)
from app.extensions import redis_client
from app.notify_client import NotifyAdminAPIClient, _attach_current_user, cache
@@ -527,10 +530,15 @@ class ServiceAPIClient(NotifyAdminAPIClient):
def get_notification_count(self, service_id):
# if cache is not set, or not enabled, return 0
-
count = redis_client.get(daily_limit_cache_key(service_id)) or 0
return int(count)
+ def get_global_notification_count(self):
+ # if cache is not set, or not enabled, return 0
+ count = redis_client.get(daily_total_cache_key()) or 0
+
+ return int(count)
+
service_api_client = ServiceAPIClient()
diff --git a/app/templates/main_nav.html b/app/templates/main_nav.html
index 757616832..133f93861 100644
--- a/app/templates/main_nav.html
+++ b/app/templates/main_nav.html
@@ -26,5 +26,15 @@
Team members
{% endif %}
-
+
+
+
Messages Left / Daily Limit
+
+ - {{ daily_remaining_messages }} / {{ current_service.message_limit }}
+
+
Messages Left Across Services
+
+ - {{ daily_global_messages_remaining }}
+
+
{% endif %}
diff --git a/app/templates/views/check/ok.html b/app/templates/views/check/ok.html
index b584b6930..c45ebc528 100644
--- a/app/templates/views/check/ok.html
+++ b/app/templates/views/check/ok.html
@@ -93,5 +93,8 @@
Only showing the first {{ count_of_displayed_recipients }} rows
{% endif %}
-
+
+
Messages remaining today / Messages left if list is sent
+
{{ remaining_messages }} / {{ remaining_messages - count_of_recipients }}
+
{% endblock %}
diff --git a/app/templates/views/send.html b/app/templates/views/send.html
index aa9481f1f..93de9bd39 100644
--- a/app/templates/views/send.html
+++ b/app/templates/views/send.html
@@ -56,4 +56,9 @@
Your file will populate this template ({{ template.name }})
{{ template|string }}
+
+
Messages Remaining Today / Daily Message Limit
+
{{ daily_remaining_messages }} / {{ current_service.message_limit }}
+
+
{% endblock %}
diff --git a/tests/app/main/views/accounts/test_choose_accounts.py b/tests/app/main/views/accounts/test_choose_accounts.py
index da12a9e8c..e04b5820d 100644
--- a/tests/app/main/views/accounts/test_choose_accounts.py
+++ b/tests/app/main/views/accounts/test_choose_accounts.py
@@ -325,7 +325,7 @@ def test_should_show_back_to_service_if_user_belongs_to_service(
):
mock_get_service.return_value = service_one
expected_page_text = (
- 'Test Service Switch service '
+ 'Test Service Switch service '
''
'Dashboard '
'Send messages '
diff --git a/tests/app/main/views/test_send.py b/tests/app/main/views/test_send.py
index 6f087dbbc..3b25c42fe 100644
--- a/tests/app/main/views/test_send.py
+++ b/tests/app/main/views/test_send.py
@@ -1751,7 +1751,7 @@ def test_upload_csvfile_with_valid_phone_shows_all_numbers(
assert '202 867 0750' not in page.text
assert 'Only showing the first 50 rows' in page.text
- mock_get_notification_count.assert_called_once_with(service_one['id'])
+ mock_get_notification_count.assert_called_with(service_id=service_one['id'])
@pytest.mark.parametrize('international_sms_permission, should_allow_international', [