Explain 3 required address columns

Our rules about address columns are relaxing, so that none of them are
mandatory any more. Instead you just need any 3 of the 7 to make a valid
address.

This commit updates our error messaging to reflect that.
This commit is contained in:
Chris Hill-Scott
2020-04-27 16:47:49 +01:00
parent b2118057ef
commit f5649d72c9
8 changed files with 35 additions and 26 deletions
+2 -9
View File
@@ -19,13 +19,8 @@ from notifications_utils import LETTER_MAX_PAGE_COUNT, SMS_CHAR_COUNT_LIMIT
from notifications_utils.columns import Columns from notifications_utils.columns import Columns
from notifications_utils.pdf import is_letter_too_long from notifications_utils.pdf import is_letter_too_long
from notifications_utils.postal_address import PostalAddress from notifications_utils.postal_address import PostalAddress
from notifications_utils.recipients import ( from notifications_utils.recipients import RecipientCSV, first_column_headings
RecipientCSV,
first_column_headings,
optional_address_columns,
)
from notifications_utils.sanitise_text import SanitiseASCII from notifications_utils.sanitise_text import SanitiseASCII
from orderedset import OrderedSet
from xlrd.biffh import XLRDError from xlrd.biffh import XLRDError
from xlrd.xldate import XLDateError from xlrd.xldate import XLDateError
@@ -663,9 +658,7 @@ def _check_messages(service_id, template_id, upload_id, preview_row, letters_as_
) )
recipients = RecipientCSV( recipients = RecipientCSV(
contents, contents,
template_type=template.template_type,
template=template, template=template,
placeholders=template.placeholders,
max_initial_rows_shown=50, max_initial_rows_shown=50,
max_errors_shown=50, max_errors_shown=50,
whitelist=itertools.chain.from_iterable( whitelist=itertools.chain.from_iterable(
@@ -711,7 +704,7 @@ def _check_messages(service_id, template_id, upload_id, preview_row, letters_as_
current_service.trial_mode, current_service.trial_mode,
template.template_type == 'letter', template.template_type == 'letter',
)), )),
required_recipient_columns=OrderedSet(recipients.recipient_column_headers) - optional_address_columns, first_recipient_column=recipients.recipient_column_headers[0],
preview_row=preview_row, preview_row=preview_row,
sent_previously=job_api_client.has_sent_previously( sent_previously=job_api_client.has_sent_previously(
service_id, template.id, db_template['version'], request.args.get('original_file_name', '') service_id, template.id, db_template['version'], request.args.get('original_file_name', '')
+2 -1
View File
@@ -43,6 +43,7 @@ from app.utils import (
generate_previous_dict, generate_previous_dict,
get_errors_for_csv, get_errors_for_csv,
get_letter_validation_error, get_letter_validation_error,
get_sample_template,
get_template, get_template,
unicode_truncate, unicode_truncate,
user_has_permissions, user_has_permissions,
@@ -357,7 +358,7 @@ def check_contact_list(service_id, upload_id):
recipients = RecipientCSV( recipients = RecipientCSV(
contents, contents,
template_type=template_type or 'sms', template=get_sample_template(template_type or 'sms'),
whitelist=itertools.chain.from_iterable( whitelist=itertools.chain.from_iterable(
[user.name, user.mobile_number, user.email_address] [user.name, user.mobile_number, user.email_address]
for user in current_service.active_users for user in current_service.active_users
+2 -1
View File
@@ -14,6 +14,7 @@ from app.s3_client.s3_csv_client import (
s3upload, s3upload,
set_metadata_on_csv_upload, set_metadata_on_csv_upload,
) )
from app.utils import get_sample_template
class ContactList(JSONModel): class ContactList(JSONModel):
@@ -119,7 +120,7 @@ class ContactList(JSONModel):
def recipients(self): def recipients(self):
return RecipientCSV( return RecipientCSV(
self.contents, self.contents,
template_type=self.template_type, template=get_sample_template(self.template_type),
international_sms=True, international_sms=True,
max_initial_rows_shown=50, max_initial_rows_shown=50,
) )
+8 -7
View File
@@ -58,15 +58,16 @@
<h1 class='banner-title' data-module="track-error" data-error-type="Missing recipient columns" data-error-label="{{ upload_id }}"> <h1 class='banner-title' data-module="track-error" data-error-type="Missing recipient columns" data-error-label="{{ upload_id }}">
Theres a problem with your column names Theres a problem with your column names
</h1> </h1>
{% if template.template_type == 'letter' %}
<p> <p>
Your file needs {{ ( Your file needs at least 3 address columns, for example address line 1,
recipients.missing_column_headers address line 2 and address line 3.
if template.template_type == 'letter' else required_recipient_columns
) | formatted_list(
prefix='a column called',
prefix_plural='columns called'
) }}.
</p> </p>
{% else %}
<p>
Your file needs a column called {{ first_recipient_column }}.
</p>
{% endif %}
<p> <p>
Right now it has {{ recipients.column_headers | formatted_list( Right now it has {{ recipients.column_headers | formatted_list(
prefix='one column, called ', prefix='one column, called ',
+10 -1
View File
@@ -151,6 +151,15 @@ def get_errors_for_csv(recipients, template_type):
return errors return errors
def get_sample_template(template_type):
if template_type == 'email':
return EmailPreviewTemplate({'content': 'any', 'subject': '', 'template_type': 'email'})
if template_type == 'sms':
return SMSPreviewTemplate({'content': 'any', 'template_type': 'sms'})
if template_type == 'letter':
return LetterImageTemplate({'content': 'any', 'subject': '', 'template_type': 'letter'})
def generate_notifications_csv(**kwargs): def generate_notifications_csv(**kwargs):
from app import notification_api_client from app import notification_api_client
from app.s3_client.s3_csv_client import s3download from app.s3_client.s3_csv_client import s3download
@@ -161,7 +170,7 @@ def generate_notifications_csv(**kwargs):
original_file_contents = s3download(kwargs['service_id'], kwargs['job_id']) original_file_contents = s3download(kwargs['service_id'], kwargs['job_id'])
original_upload = RecipientCSV( original_upload = RecipientCSV(
original_file_contents, original_file_contents,
template_type=kwargs['template_type'], template=get_sample_template(kwargs['template_type']),
) )
original_column_headers = original_upload.column_headers original_column_headers = original_upload.column_headers
fieldnames = ['Row number'] + original_column_headers + ['Template', 'Type', 'Job', 'Status', 'Time'] fieldnames = ['Row number'] + original_column_headers + ['Template', 'Type', 'Job', 'Status', 'Time']
+1 -1
View File
@@ -24,5 +24,5 @@ WTForms==2.2.1 # Pinned because of breaking change in 2.3.0
awscli-cwlogs>=1.4,<1.5 awscli-cwlogs>=1.4,<1.5
itsdangerous==1.1.0 itsdangerous==1.1.0
git+https://github.com/alphagov/notifications-utils.git@37.3.0#egg=notifications-utils==37.3.0 git+https://github.com/alphagov/notifications-utils.git@38.0.0#egg=notifications-utils==38.0.0
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
+3 -3
View File
@@ -26,14 +26,14 @@ WTForms==2.2.1 # Pinned because of breaking change in 2.3.0
awscli-cwlogs>=1.4,<1.5 awscli-cwlogs>=1.4,<1.5
itsdangerous==1.1.0 itsdangerous==1.1.0
git+https://github.com/alphagov/notifications-utils.git@37.3.0#egg=notifications-utils==37.3.0 git+https://github.com/alphagov/notifications-utils.git@38.0.0#egg=notifications-utils==38.0.0
git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha git+https://github.com/alphagov/govuk-frontend-jinja.git@v0.5.1-alpha#egg=govuk-frontend-jinja==0.5.1-alpha
## The following requirements were added by pip freeze: ## The following requirements were added by pip freeze:
awscli==1.18.43 awscli==1.18.46
bleach==3.1.4 bleach==3.1.4
boto3==1.10.38 boto3==1.10.38
botocore==1.15.43 botocore==1.15.46
certifi==2020.4.5.1 certifi==2020.4.5.1
chardet==3.0.4 chardet==3.0.4
click==7.1.1 click==7.1.1
+7 -3
View File
@@ -19,6 +19,7 @@ from notifications_utils.recipients import RecipientCSV
from notifications_utils.template import ( from notifications_utils.template import (
LetterImageTemplate, LetterImageTemplate,
LetterPreviewTemplate, LetterPreviewTemplate,
SMSPreviewTemplate,
) )
from xlrd.biffh import XLRDError from xlrd.biffh import XLRDError
from xlrd.xldate import ( from xlrd.xldate import (
@@ -2575,7 +2576,9 @@ def test_upload_csvfile_with_international_validates(
mocker.patch('app.main.views.send.s3download', return_value='') mocker.patch('app.main.views.send.s3download', return_value='')
mock_recipients = mocker.patch( mock_recipients = mocker.patch(
'app.main.views.send.RecipientCSV', 'app.main.views.send.RecipientCSV',
return_value=RecipientCSV("", template_type="sms"), return_value=RecipientCSV("", template=SMSPreviewTemplate(
{'content': 'foo', 'template_type': 'sms'}
)),
) )
response = logged_in_client.post( response = logged_in_client.post(
@@ -3381,7 +3384,7 @@ def test_check_messages_shows_data_errors_before_trial_mode_errors_for_letters(
assert normalize_spaces(page.select_one('.banner-dangerous').text) == ( assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
'Theres a problem with example.xlsx ' 'Theres a problem with example.xlsx '
'You need to enter missing data in 2 rows. ' 'You need to fix 2 addresses. '
'Skip to file contents' 'Skip to file contents'
) )
assert not page.select('.table-field-index a') assert not page.select('.table-field-index a')
@@ -3470,7 +3473,8 @@ def test_check_messages_column_error_doesnt_show_optional_columns(
assert normalize_spaces(page.select_one('.banner-dangerous').text) == ( assert normalize_spaces(page.select_one('.banner-dangerous').text) == (
'Theres a problem with your column names ' 'Theres a problem with your column names '
'Your file needs a column called postcode. ' 'Your file needs at least 3 address columns, for example address line 1, '
'address line 2 and address line 3. '
'Right now it has columns called address_line_1, address_line_2 and foo. ' 'Right now it has columns called address_line_1, address_line_2 and foo. '
'Skip to file contents' 'Skip to file contents'
) )