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