diff --git a/app/utils.py b/app/utils.py
index 71e058fd3..9f3d9483e 100644
--- a/app/utils.py
+++ b/app/utils.py
@@ -17,7 +17,10 @@ from dateutil import parser
from flask import abort, current_app, redirect, request, session, url_for
from flask_login import current_user, login_required
from notifications_utils.field import Field
-from notifications_utils.formatters import make_quotes_smart
+from notifications_utils.formatters import (
+ make_quotes_smart,
+ unescaped_formatted_list,
+)
from notifications_utils.letter_timings import letter_can_be_cancelled
from notifications_utils.recipients import RecipientCSV
from notifications_utils.take import Take
@@ -544,6 +547,54 @@ def get_letter_printing_statement(status, created_at):
return 'Printed on {} at 5:30pm'.format(printed_date)
+LETTER_VALIDATION_MESSAGES = {
+ 'letter-not-a4-portrait-oriented': {
+ 'title': 'We cannot print your letter',
+ 'detail': 'Your letter is not A4 portrait size on {invalid_pages}
'
+ 'Files must meet our letter specification.'
+ },
+ 'content-outside-printable-area': {
+ 'title': 'We cannot print your letter',
+ 'detail': 'The content appears outside the printable area on {invalid_pages}
'
+ 'Files must meet our letter specification.'
+ },
+ 'letter-too-long': {
+ 'title': 'Your letter is too long',
+ 'detail': 'Letters must be 10 pages or less.
Your letter is {page_count} pages long.'
+ },
+ 'no-encoded-string': {
+ 'title': 'Sanitise failed - No encoded string'
+ },
+ 'unable-to-read-the-file': {
+ 'title': 'There’s a problem with your file',
+ 'detail': 'Notify cannot read this PDF.
Save a new copy of your file and try again.'
+ }
+}
+
+
+def get_letter_validation_error(validation_message, invalid_pages=None, page_count=None):
+ if validation_message not in LETTER_VALIDATION_MESSAGES:
+ return {'title': 'Validation failed'}
+
+ invalid_pages = unescaped_formatted_list(
+ invalid_pages or [],
+ before_each='',
+ after_each='',
+ prefix='page',
+ prefix_plural='pages'
+ )
+
+ return {
+ 'title': LETTER_VALIDATION_MESSAGES[validation_message]['title'],
+ 'detail': LETTER_VALIDATION_MESSAGES[validation_message]['detail'].format(
+ invalid_pages=invalid_pages,
+ page_count=page_count,
+ )
+ }
+
+
class PermanentRedirect(RequestRedirect):
"""
In Werkzeug 0.15.0 the status code for RequestRedirect changed from 301 to 308.
diff --git a/tests/app/test_utils.py b/tests/app/test_utils.py
index b230188ad..cb493adeb 100644
--- a/tests/app/test_utils.py
+++ b/tests/app/test_utils.py
@@ -14,6 +14,7 @@ from app.utils import (
generate_notifications_csv,
generate_previous_dict,
get_letter_printing_statement,
+ get_letter_validation_error,
get_logo_cdn_domain,
printing_today_or_tomorrow,
)
@@ -404,3 +405,25 @@ def test_get_letter_printing_statement_for_letter_that_has_been_sent(created_at,
statement = get_letter_printing_statement('delivered', created_at)
assert statement == 'Printed {} at 5:30pm'.format(print_day)
+
+
+def test_get_letter_validation_error_for_unknown_error():
+ assert get_letter_validation_error('Unknown error') == {
+ 'title': 'Validation failed'
+ }
+
+
+@pytest.mark.parametrize('error_message, expected_title, expected_content', [
+ ('letter-not-a4-portrait-oriented', 'We cannot print your letter', 'A4 portrait size on page 2'),
+ ('content-outside-printable-area', 'We cannot print your letter', 'outside the printable area on page 2'),
+ ('letter-too-long', 'Your letter is too long', 'letter is 13 pages long.')
+])
+def test_get_letter_validation_error_for_known_errors(
+ error_message,
+ expected_title,
+ expected_content,
+):
+ error = get_letter_validation_error(error_message, invalid_pages=[2], page_count=13)
+
+ assert error['title'] == expected_title
+ assert expected_content in error['detail']