diff --git a/app/main/forms.py b/app/main/forms.py index 5b0f74f4d..f126ec7d0 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -1174,6 +1174,15 @@ class FreeSMSAllowance(StripWhitespaceForm): ) +class MessageLimit(StripWhitespaceForm): + message_limit = GovukIntegerField( + 'Number of messages the service is allowed to send each day', + validators=[ + DataRequired(message='Cannot be empty') + ] + ) + + class ConfirmPasswordForm(StripWhitespaceForm): def __init__(self, validate_password_func, *args, **kwargs): self.validate_password_func = validate_password_func diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 2e7fc6430..0430b99b8 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -36,6 +36,7 @@ from app.main.forms import ( EstimateUsageForm, FreeSMSAllowance, LinkOrganisationsForm, + MessageLimit, PreviewBranding, RenameServiceForm, SearchByNameForm, @@ -938,6 +939,23 @@ def set_free_sms_allowance(service_id): ) +@main.route("/services//service-settings/set-message-limit", methods=['GET', 'POST']) +@user_is_platform_admin +def set_message_limit(service_id): + + form = MessageLimit(message_limit=current_service.message_limit) + + if form.validate_on_submit(): + current_service.update(message_limit=form.message_limit.data) + + return redirect(url_for('.service_settings', service_id=service_id)) + + return render_template( + 'views/service-settings/set-message-limit.html', + form=form, + ) + + @main.route("/services//service-settings/set-email-branding", methods=['GET', 'POST']) @user_is_platform_admin def service_set_email_branding(service_id): diff --git a/app/navigation.py b/app/navigation.py index bce698bec..652ca605c 100644 --- a/app/navigation.py +++ b/app/navigation.py @@ -316,6 +316,7 @@ class HeaderNavigation(Navigation): 'service_verify_reply_to_address_updates', 'services_or_dashboard', 'set_free_sms_allowance', + 'set_message_limit', 'set_sender', 'set_template_sender', 'show_accounts_or_dashboard', @@ -503,6 +504,7 @@ class MainNavigation(Navigation): 'service_settings', 'service_sms_senders', 'set_free_sms_allowance', + 'set_message_limit', 'service_set_letter_branding', 'submit_request_to_go_live', }, @@ -969,6 +971,7 @@ class CaseworkNavigation(Navigation): 'service_verify_reply_to_address_updates', 'services_or_dashboard', 'set_free_sms_allowance', + 'set_message_limit', 'service_set_letter_branding', 'set_sender', 'set_template_sender', @@ -1281,6 +1284,7 @@ class OrgNavigation(Navigation): 'service_verify_reply_to_address_updates', 'services_or_dashboard', 'set_free_sms_allowance', + 'set_message_limit', 'service_set_letter_branding', 'set_sender', 'set_template_sender', diff --git a/app/templates/views/service-settings.html b/app/templates/views/service-settings.html index 5f43353ed..9f20a431d 100644 --- a/app/templates/views/service-settings.html +++ b/app/templates/views/service-settings.html @@ -353,10 +353,14 @@ {% endcall %} {{ edit_field('Change', url_for('.link_service_to_organisation', service_id=current_service.id), suffix='organisation for service') }} {% endcall %} - + {% call row() %} + {{ text_field('Message limit')}} + {{ text_field('{:,} per day'.format(current_service.message_limit)) }} + {{ edit_field('Change', url_for('.set_message_limit', service_id=current_service.id), suffix='daily message limit') }} + {% endcall %} {% call row() %} {{ text_field('Free text message allowance')}} - {{ text_field('{:,}'.format(current_service.free_sms_fragment_limit)) }} + {{ text_field('{:,} per year'.format(current_service.free_sms_fragment_limit)) }} {{ edit_field('Change', url_for('.set_free_sms_allowance', service_id=current_service.id), suffix='free text message allowance') }} {% endcall %} {% call row() %} diff --git a/app/templates/views/service-settings/set-message-limit.html b/app/templates/views/service-settings/set-message-limit.html new file mode 100644 index 000000000..2cdb5872b --- /dev/null +++ b/app/templates/views/service-settings/set-message-limit.html @@ -0,0 +1,21 @@ +{% extends "withnav_template.html" %} +{% from "components/page-header.html" import page_header %} +{% from "components/page-footer.html" import page_footer %} +{% from "components/form.html" import form_wrapper %} + +{% block service_page_title %} + Set daily message limit +{% endblock %} + +{% block maincolumn_content %} + + {% call form_wrapper() %} + {{ page_header( + 'Daily message limit', + back_link=url_for('.service_settings', service_id=current_service.id) + ) }} + {{ form.message_limit }} + {{ page_footer('Save') }} + {% endcall %} + +{% endblock %} diff --git a/tests/app/main/views/test_service_settings.py b/tests/app/main/views/test_service_settings.py index 6f25abbb7..b4e35edee 100644 --- a/tests/app/main/views/test_service_settings.py +++ b/tests/app/main/views/test_service_settings.py @@ -101,7 +101,8 @@ def mock_get_service_settings_page_common( 'Live Off Change service status', 'Count in list of live services Yes Change if service is counted in list of live services', 'Organisation Test organisation Central government Change organisation for service', - 'Free text message allowance 250,000 Change free text message allowance', + 'Message limit 1,000 per day Change daily message limit', + 'Free text message allowance 250,000 per year Change free text message allowance', 'Email branding GOV.UK Change email branding (admin view)', 'Letter branding Not set Change letter branding (admin view)', 'Data retention email Change data retention', @@ -3577,6 +3578,7 @@ def test_should_set_branding_and_organisations( @pytest.mark.parametrize('method', ['get', 'post']) @pytest.mark.parametrize('endpoint', [ 'main.set_free_sms_allowance', + 'main.set_message_limit', ]) def test_organisation_type_pages_are_platform_admin_only( client_request, @@ -3638,6 +3640,54 @@ def test_should_set_sms_allowance( ) +def test_should_show_page_to_set_message_limit( + platform_admin_client, +): + response = platform_admin_client.get(url_for( + 'main.set_message_limit', + service_id=SERVICE_ONE_ID + )) + assert response.status_code == 200 + page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') + + assert normalize_spaces(page.select_one('label').text) == ( + 'Number of messages the service is allowed to send each day' + ) + assert normalize_spaces(page.select_one('input[type=text]')['value']) == ( + '1000' + ) + + +@pytest.mark.parametrize('new_limit, expected_api_argument', [ + ('1', 1), + ('250000', 250000), + pytest.param('foo', 'foo', marks=pytest.mark.xfail), +]) +def test_should_set_message_limit( + platform_admin_client, + new_limit, + expected_api_argument, + mock_update_service, +): + + response = platform_admin_client.post( + url_for( + 'main.set_message_limit', + service_id=SERVICE_ONE_ID, + ), + data={ + 'message_limit': new_limit, + }, + ) + assert response.status_code == 302 + assert response.location == url_for('main.service_settings', service_id=SERVICE_ONE_ID, _external=True) + + mock_update_service.assert_called_once_with( + SERVICE_ONE_ID, + message_limit=expected_api_argument, + ) + + def test_old_set_letters_page_redirects( client_request, ):