diff --git a/app/main/forms.py b/app/main/forms.py index c99eeef22..016534ed4 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -40,7 +40,7 @@ from app.main.validators import ( DoesNotStartWithDoubleZero, LettersNumbersAndFullStopsOnly, NoCommasInPlaceHolders, - OnlyGSMCharacters, + OnlySMSCharacters, ValidEmail, ValidGovEmail, ) @@ -639,7 +639,7 @@ class BaseTemplateForm(StripWhitespaceForm): class SMSTemplateForm(BaseTemplateForm): def validate_template_content(self, field): - OnlyGSMCharacters()(None, field) + OnlySMSCharacters()(None, field) class EmailTemplateForm(BaseTemplateForm): diff --git a/app/main/validators.py b/app/main/validators.py index 216038726..b7dfb25a7 100644 --- a/app/main/validators.py +++ b/app/main/validators.py @@ -5,7 +5,7 @@ from notifications_utils.recipients import ( InvalidEmailError, validate_email_address, ) -from notifications_utils.sanitise_text import SanitiseGSM +from notifications_utils.sanitise_text import SanitiseSMS from wtforms import ValidationError from wtforms.validators import Email @@ -79,14 +79,14 @@ class NoCommasInPlaceHolders: raise ValidationError(self.message) -class OnlyGSMCharacters: +class OnlySMSCharacters: def __call__(self, form, field): - non_gsm_characters = sorted(list(SanitiseGSM.get_non_compatible_characters(field.data))) - if non_gsm_characters: + non_sms_characters = sorted(list(SanitiseSMS.get_non_compatible_characters(field.data))) + if non_sms_characters: raise ValidationError( 'You can’t use {} in text messages. {} won’t show up properly on everyone’s phones.'.format( - formatted_list(non_gsm_characters, conjunction='or', before_each='', after_each=''), - ('It' if len(non_gsm_characters) == 1 else 'They') + formatted_list(non_sms_characters, conjunction='or', before_each='', after_each=''), + ('It' if len(non_sms_characters) == 1 else 'They') ) ) diff --git a/app/main/views/conversation.py b/app/main/views/conversation.py index e9d5dfeb6..e3ef576df 100644 --- a/app/main/views/conversation.py +++ b/app/main/views/conversation.py @@ -127,7 +127,7 @@ def get_sms_thread(service_id, user_number): ) }, notification.get('personalisation'), - downgrade_non_gsm_characters=(not is_inbound), + downgrade_non_sms_characters=(not is_inbound), redact_missing_personalisation=redact_personalisation, ), 'created_at': notification['created_at'], diff --git a/app/templates/views/pricing.html b/app/templates/views/pricing.html index e54df2e7d..68073cc7b 100644 --- a/app/templates/views/pricing.html +++ b/app/templates/views/pricing.html @@ -40,10 +40,10 @@

See how to pay.

Long text messages

-

If a text message is beyond a certain length, it’ll be charged as more than one message:

+

If a text message is longer than 160 characters (including spaces), it’ll be charged as more than one message:

{% call mapping_table( - caption='Letter pricing', + caption='Text message pricing', field_headings=['Message length', 'Charge'], field_headings_visible=True, caption_visible=False @@ -61,6 +61,29 @@ {% endfor %} {% endcall %}
+

Text messages containing Welsh characters

+

Long text messages containing Welsh characters (Â, â, Ê, ê, Î, î, Ô, ô, Û, û, Ŵ, ŵ, Ŷ, and ŷ) are charged differently:

+
+ {% call mapping_table( + caption='Text message pricing', + field_headings=['Message length', 'Charge'], + field_headings_visible=True, + caption_visible=False + ) %} + {% for message_length, charge in [ + ('Up to 70 characters', '1 text message'), + ('Up to 134 characters', '2 text messages'), + ('Up to 201 characters', '3 text messages'), + ('Up to 268 characters', '4 text messages'), + ('Each additional 67 characters', '1 additional text message'), + ] %} + {% call row() %} + {{ text_field(message_length) }} + {{ text_field(charge) }} + {% endcall %} + {% endfor %} + {% endcall %} +

Sending text messages to international numbers

It might cost more to send text messages to international numbers than UK ones, depending on the country.

diff --git a/requirements-app.txt b/requirements-app.txt index 343b87a89..ee9fa1966 100644 --- a/requirements-app.txt +++ b/requirements-app.txt @@ -23,4 +23,4 @@ awscli-cwlogs>=1.4,<1.5 # Putting upgrade on hold due to v1.0.0 using sha512 instead of sha1 by default itsdangerous==0.24 # pyup: <1.0.0 -git+https://github.com/alphagov/notifications-utils.git@31.2.6#egg=notifications-utils==31.2.6 +git+https://github.com/alphagov/notifications-utils.git@32.0.0#egg=notifications-utils==32.0.0 diff --git a/requirements.txt b/requirements.txt index 178f9d16f..4c63dd55e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,7 +25,7 @@ awscli-cwlogs>=1.4,<1.5 # Putting upgrade on hold due to v1.0.0 using sha512 instead of sha1 by default itsdangerous==0.24 # pyup: <1.0.0 -git+https://github.com/alphagov/notifications-utils.git@31.2.6#egg=notifications-utils==31.2.6 +git+https://github.com/alphagov/notifications-utils.git@32.0.0#egg=notifications-utils==32.0.0 ## The following requirements were added by pip freeze: awscli==1.16.155 diff --git a/tests/app/main/test_validators.py b/tests/app/main/test_validators.py index b243ccf83..7d96004cb 100644 --- a/tests/app/main/test_validators.py +++ b/tests/app/main/test_validators.py @@ -6,7 +6,7 @@ from wtforms import ValidationError from app.main.forms import RegisterUserForm, ServiceSmsSenderForm from app.main.validators import ( NoCommasInPlaceHolders, - OnlyGSMCharacters, + OnlySMSCharacters, ValidGovEmail, ) @@ -165,8 +165,8 @@ def test_for_commas_in_placeholders( @pytest.mark.parametrize('msg', ['The quick brown fox', 'Thé “quick” bröwn fox\u200B']) -def test_gsm_character_validation(client, msg): - OnlyGSMCharacters()(None, _gen_mock_field(msg)) +def test_sms_character_validation(client, msg): + OnlySMSCharacters()(None, _gen_mock_field(msg)) @pytest.mark.parametrize('data, err_msg', [ @@ -185,9 +185,9 @@ def test_gsm_character_validation(client, msg): ) ), ]) -def test_non_gsm_character_validation(data, err_msg, client): +def test_non_sms_character_validation(data, err_msg, client): with pytest.raises(ValidationError) as error: - OnlyGSMCharacters()(None, _gen_mock_field(data)) + OnlySMSCharacters()(None, _gen_mock_field(data)) assert str(error.value) == err_msg