Allow Welsh characters in SMS

- This brings in the latest version of notifications-utils which
allows Welsh characters in SMS templates.
- Updated the pricing page to show the new prices for SMS with certain
Welsh characters
This commit is contained in:
Katie Smith
2019-05-03 15:13:39 +01:00
parent 00e7ccadad
commit 5be6b41195
7 changed files with 41 additions and 18 deletions

View File

@@ -40,7 +40,7 @@ from app.main.validators import (
DoesNotStartWithDoubleZero, DoesNotStartWithDoubleZero,
LettersNumbersAndFullStopsOnly, LettersNumbersAndFullStopsOnly,
NoCommasInPlaceHolders, NoCommasInPlaceHolders,
OnlyGSMCharacters, OnlySMSCharacters,
ValidEmail, ValidEmail,
ValidGovEmail, ValidGovEmail,
) )
@@ -639,7 +639,7 @@ class BaseTemplateForm(StripWhitespaceForm):
class SMSTemplateForm(BaseTemplateForm): class SMSTemplateForm(BaseTemplateForm):
def validate_template_content(self, field): def validate_template_content(self, field):
OnlyGSMCharacters()(None, field) OnlySMSCharacters()(None, field)
class EmailTemplateForm(BaseTemplateForm): class EmailTemplateForm(BaseTemplateForm):

View File

@@ -5,7 +5,7 @@ from notifications_utils.recipients import (
InvalidEmailError, InvalidEmailError,
validate_email_address, validate_email_address,
) )
from notifications_utils.sanitise_text import SanitiseGSM from notifications_utils.sanitise_text import SanitiseSMS
from wtforms import ValidationError from wtforms import ValidationError
from wtforms.validators import Email from wtforms.validators import Email
@@ -79,14 +79,14 @@ class NoCommasInPlaceHolders:
raise ValidationError(self.message) raise ValidationError(self.message)
class OnlyGSMCharacters: class OnlySMSCharacters:
def __call__(self, form, field): def __call__(self, form, field):
non_gsm_characters = sorted(list(SanitiseGSM.get_non_compatible_characters(field.data))) non_sms_characters = sorted(list(SanitiseSMS.get_non_compatible_characters(field.data)))
if non_gsm_characters: if non_sms_characters:
raise ValidationError( raise ValidationError(
'You cant use {} in text messages. {} wont show up properly on everyones phones.'.format( 'You cant use {} in text messages. {} wont show up properly on everyones phones.'.format(
formatted_list(non_gsm_characters, conjunction='or', before_each='', after_each=''), formatted_list(non_sms_characters, conjunction='or', before_each='', after_each=''),
('It' if len(non_gsm_characters) == 1 else 'They') ('It' if len(non_sms_characters) == 1 else 'They')
) )
) )

View File

@@ -127,7 +127,7 @@ def get_sms_thread(service_id, user_number):
) )
}, },
notification.get('personalisation'), notification.get('personalisation'),
downgrade_non_gsm_characters=(not is_inbound), downgrade_non_sms_characters=(not is_inbound),
redact_missing_personalisation=redact_personalisation, redact_missing_personalisation=redact_personalisation,
), ),
'created_at': notification['created_at'], 'created_at': notification['created_at'],

View File

@@ -40,10 +40,10 @@
<p>See <a href="#paying">how to pay</a>. <p>See <a href="#paying">how to pay</a>.
<h3 class="heading-small">Long text messages</h3> <h3 class="heading-small">Long text messages</h3>
<p>If a text message is beyond a certain length, itll be charged as more than one message:</p> <p>If a text message is longer than 160 characters (including spaces), itll be charged as more than one message:</p>
<div class="bottom-gutter-3-2"> <div class="bottom-gutter-3-2">
{% call mapping_table( {% call mapping_table(
caption='Letter pricing', caption='Text message pricing',
field_headings=['Message length', 'Charge'], field_headings=['Message length', 'Charge'],
field_headings_visible=True, field_headings_visible=True,
caption_visible=False caption_visible=False
@@ -61,6 +61,29 @@
{% endfor %} {% endfor %}
{% endcall %} {% endcall %}
</div> </div>
<h3 class="heading-small">Text messages containing Welsh characters</h3>
<p>Long text messages containing Welsh characters (Â, â, Ê, ê, Î, î, Ô, ô, Û, û, Ŵ, ŵ, Ŷ, and ŷ) are charged differently:</p>
<div class="bottom-gutter-3-2">
{% 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 %}
</div>
<h3 class="heading-small">Sending text messages to international numbers</h3> <h3 class="heading-small">Sending text messages to international numbers</h3>
<p>It might cost more to send text messages to international numbers than UK ones, depending on the country.</p> <p>It might cost more to send text messages to international numbers than UK ones, depending on the country.</p>
<details> <details>

View File

@@ -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 # Putting upgrade on hold due to v1.0.0 using sha512 instead of sha1 by default
itsdangerous==0.24 # pyup: <1.0.0 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

View File

@@ -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 # Putting upgrade on hold due to v1.0.0 using sha512 instead of sha1 by default
itsdangerous==0.24 # pyup: <1.0.0 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: ## The following requirements were added by pip freeze:
awscli==1.16.155 awscli==1.16.155

View File

@@ -6,7 +6,7 @@ from wtforms import ValidationError
from app.main.forms import RegisterUserForm, ServiceSmsSenderForm from app.main.forms import RegisterUserForm, ServiceSmsSenderForm
from app.main.validators import ( from app.main.validators import (
NoCommasInPlaceHolders, NoCommasInPlaceHolders,
OnlyGSMCharacters, OnlySMSCharacters,
ValidGovEmail, 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']) @pytest.mark.parametrize('msg', ['The quick brown fox', 'Thé “quick” bröwn fox\u200B'])
def test_gsm_character_validation(client, msg): def test_sms_character_validation(client, msg):
OnlyGSMCharacters()(None, _gen_mock_field(msg)) OnlySMSCharacters()(None, _gen_mock_field(msg))
@pytest.mark.parametrize('data, err_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: with pytest.raises(ValidationError) as error:
OnlyGSMCharacters()(None, _gen_mock_field(data)) OnlySMSCharacters()(None, _gen_mock_field(data))
assert str(error.value) == err_msg assert str(error.value) == err_msg