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', [