From 9581a3bb774805017187c93a48f0b8d9e5dd0ac7 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Tue, 26 Sep 2017 14:05:02 +0100 Subject: [PATCH] Allow services to turn international SMS on/off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We didn’t make this self-service before because the pricing information wasn’t published (ie we had to send it to services that asked for it). Now that we publish pricing information in the app, there’s no reason why services can’t make an informed decision about whether they want international SMS or not. So this commit: - removes the platform admin button - adds some radio buttons that our users can click with their mice --- app/main/forms.py | 10 +++ app/main/views/service_settings.py | 38 ++++++-- app/templates/views/service-settings.html | 5 -- .../set-international-sms.html | 39 ++++----- tests/app/main/views/test_service_settings.py | 86 ++++++++++--------- 5 files changed, 102 insertions(+), 76 deletions(-) diff --git a/app/main/forms.py b/app/main/forms.py index b66950051..b16f46a42 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -658,6 +658,16 @@ class ServiceInboundApiForm(Form): Length(min=10, message='Must be at least 10 characters')]) +class InternationalSMSForm(Form): + enabled = RadioField( + 'Send text messages to international phone numbers', + choices=[ + ('on', 'On'), + ('off', 'Off'), + ], + ) + + def get_placeholder_form_instance( placeholder_name, dict_to_populate_from, diff --git a/app/main/views/service_settings.py b/app/main/views/service_settings.py index 866d19873..2f1d1472f 100644 --- a/app/main/views/service_settings.py +++ b/app/main/views/service_settings.py @@ -32,7 +32,9 @@ from app.main.forms import ( ServiceLetterContactBlock, ServiceBrandingOrg, LetterBranding, - ServiceInboundApiForm) + ServiceInboundApiForm, + InternationalSMSForm, +) from app import user_api_client, current_service, organisations_client, inbound_number_client @@ -222,13 +224,22 @@ def service_switch_research_mode(service_id): return redirect(url_for('.service_settings', service_id=service_id)) -def switch_service_permissions(service_id, permission, sms_sender=None): +def switch_service_permissions(service_id, permission, sms_sender=None, force=None): + permissions = current_service['permissions'].copy() - if permission in permissions: - permissions.remove(permission) + + if force is None: + if permission in permissions: + permissions.remove(permission) + else: + permissions.append(permission) else: - permissions.append(permission) - current_service['permissions'] = permissions + if force is True: + permissions.append(permission) + elif force is False and permission in permissions: + permissions.remove(permission) + + current_service['permissions'] = list(set(permissions)) data = {'permissions': permissions} if sms_sender: @@ -423,12 +434,25 @@ def service_set_sms(service_id): ) -@main.route("/services//service-settings/set-international-sms", methods=['GET']) +@main.route("/services//service-settings/set-international-sms", methods=['GET', 'POST']) @login_required @user_has_permissions('manage_settings', admin_override=True) def service_set_international_sms(service_id): + form = InternationalSMSForm( + enabled='on' if 'international_sms' in current_service['permissions'] else 'off' + ) + if form.validate_on_submit(): + switch_service_permissions( + service_id, + 'international_sms', + force=False if form.enabled.data == 'off' else True, + ) + return redirect( + url_for(".service_settings", service_id=service_id) + ) return render_template( 'views/service-settings/set-international-sms.html', + form=form, ) diff --git a/app/templates/views/service-settings.html b/app/templates/views/service-settings.html index 193705cf1..ebce22710 100644 --- a/app/templates/views/service-settings.html +++ b/app/templates/views/service-settings.html @@ -231,11 +231,6 @@ {% if 'sms' in current_service.permissions %} -
  • - - {{ 'Stop sending international sms' if 'international_sms' in current_service.permissions else 'Allow to send international sms' }} - -
  • {% if can_receive_inbound %} diff --git a/app/templates/views/service-settings/set-international-sms.html b/app/templates/views/service-settings/set-international-sms.html index 6b0c683eb..13568c94a 100644 --- a/app/templates/views/service-settings/set-international-sms.html +++ b/app/templates/views/service-settings/set-international-sms.html @@ -1,5 +1,5 @@ {% extends "withnav_template.html" %} -{% from "components/textbox.html" import textbox %} +{% from "components/radios.html" import radios %} {% from "components/page-footer.html" import page_footer %} {% block service_page_title %} @@ -11,28 +11,21 @@

    International text messages

    - {% if 'international_sms' in current_service.permissions %} -

    - Your service can send text messages to international phone numbers. -

    -

    - If you want to turn it off, - get in touch with the GOV.UK Notify team. -

    - {% else %} -

    - Sending text messages to international phone numbers is an - invitation‑only feature. -

    -

    - If you want to try it out, - get in touch with the GOV.UK Notify team. -

    - {% endif %} - {{ page_footer( - back_link=url_for('.service_settings', service_id=current_service.id), - back_link_text='Back to settings' - ) }} +

    + Messages to international mobile numbers are charged at 1, 2, or + 3 times the cost of messages to UK mobile numbers.

    +

    + See pricing for the list + of rates. +

    +
    + {{ radios(form.enabled) }} + {{ page_footer( + button_text="Save", + back_link=url_for('.service_settings', service_id=current_service.id), + back_link_text='Back to settings' + ) }} +
    diff --git a/tests/app/main/views/test_service_settings.py b/tests/app/main/views/test_service_settings.py index ec0eacef4..e720f01c6 100644 --- a/tests/app/main/views/test_service_settings.py +++ b/tests/app/main/views/test_service_settings.py @@ -1176,40 +1176,59 @@ def test_switch_service_disable_letters( assert mocked_fn.call_args == call(service_one['id'], {"permissions": []}) +@pytest.mark.parametrize('permissions, expected_checked', [ + (['international_sms'], 'on'), + ([''], 'off'), +]) +def test_show_international_sms_as_radio_button( + client_request, + service_one, + mocker, + permissions, + expected_checked, +): + service_one['permissions'] = permissions + + checked_radios = client_request.get( + 'main.service_set_international_sms', + service_id=service_one['id'], + ).select( + '.multiple-choice input[checked]' + ) + + assert len(checked_radios) == 1 + assert checked_radios[0]['value'] == expected_checked + + +@pytest.mark.parametrize('post_value, international_sms_permission_expected_in_api_call', [ + ('on', True), + ('off', False), +]) def test_switch_service_enable_international_sms( - logged_in_platform_admin_client, - service_one, - mocker, + client_request, + service_one, + mocker, + post_value, + international_sms_permission_expected_in_api_call, ): mocked_fn = mocker.patch('app.service_api_client.update_service_with_properties', return_value=service_one) - - response = logged_in_platform_admin_client.get( - url_for('main.service_switch_can_send_international_sms', service_id=service_one['id']) + page = client_request.post( + 'main.service_set_international_sms', + service_id=service_one['id'], + _data={ + 'enabled': post_value + }, + _expected_redirect=url_for('main.service_settings', service_id=service_one['id'], _external=True) ) - assert response.status_code == 302 - assert response.location == url_for('main.service_settings', service_id=service_one['id'], _external=True) - assert 'international_sms' in mocked_fn.call_args[0][1]['permissions'] + if international_sms_permission_expected_in_api_call: + assert 'international_sms' in mocked_fn.call_args[0][1]['permissions'] + else: + assert 'international_sms' not in mocked_fn.call_args[0][1]['permissions'] + assert mocked_fn.call_args[0][0] == service_one['id'] -def test_switch_service_disable_international_sms( - logged_in_platform_admin_client, - service_one, - mocker, -): - service_one['permissions'] = ['international_sms'] - mocked_fn = mocker.patch('app.service_api_client.update_service_with_properties', return_value=service_one) - - response = logged_in_platform_admin_client.get( - url_for('main.service_switch_can_send_international_sms', service_id=service_one['id']) - ) - - assert response.status_code == 302 - assert response.location == url_for('main.service_settings', service_id=service_one['id'], _external=True) - assert mocked_fn.call_args == call(service_one['id'], {"permissions": []}) - - def test_set_new_inbound_api_and_valid_bearer_token_calls_create_inbound_api_endpoint( logged_in_platform_admin_client, service_one, @@ -1466,21 +1485,6 @@ def test_cant_resume_active_service( @pytest.mark.parametrize('endpoint, permissions, expected_p', [ - ( - 'main.service_set_international_sms', - ['sms'], - ( - 'Sending text messages to international phone numbers is ' - 'an invitation‑only feature.' - ) - ), - ( - 'main.service_set_international_sms', - ['sms', 'international_sms'], - ( - 'Your service can send text messages to international phone numbers.' - ) - ), ( 'main.service_set_letters', [],