mirror of
https://github.com/GSA/notifications-admin.git
synced 2026-08-06 06:31:33 -04:00
Merge pull request #2539 from alphagov/sending-content-changes
Content changes for notification pages
This commit is contained in:
@@ -32,6 +32,7 @@ from app.utils import (
|
||||
get_page_from_request,
|
||||
get_time_left,
|
||||
parse_filter_args,
|
||||
printing_today_or_tomorrow,
|
||||
set_status_filters,
|
||||
user_has_permissions,
|
||||
)
|
||||
@@ -92,6 +93,11 @@ def view_job(service_id, job_id):
|
||||
version=job['template_version']
|
||||
)['data']
|
||||
|
||||
just_sent_message = 'Your {} been sent. Printing starts {} at 5.30pm.'.format(
|
||||
'letter has' if job['notification_count'] == 1 else 'letters have',
|
||||
printing_today_or_tomorrow()
|
||||
)
|
||||
|
||||
return render_template(
|
||||
'views/jobs/job.html',
|
||||
finished=(total_notifications == processed_notifications),
|
||||
@@ -108,7 +114,8 @@ def view_job(service_id, job_id):
|
||||
just_sent=bool(
|
||||
request.args.get('just_sent') == 'yes' and
|
||||
template['template_type'] == 'letter'
|
||||
)
|
||||
),
|
||||
just_sent_message=just_sent_message,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
import base64
|
||||
import io
|
||||
import os
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from dateutil import parser
|
||||
from flask import (
|
||||
Response,
|
||||
abort,
|
||||
@@ -16,10 +17,15 @@ from flask import (
|
||||
)
|
||||
from flask_login import login_required
|
||||
from notifications_python_client.errors import APIError
|
||||
from notifications_utils.letter_timings import get_letter_timings
|
||||
from notifications_utils.letter_timings import (
|
||||
get_letter_timings,
|
||||
letter_can_be_cancelled,
|
||||
)
|
||||
from notifications_utils.pdf import pdf_page_count
|
||||
from notifications_utils.timezones import utc_string_to_aware_gmt_datetime
|
||||
|
||||
from app import (
|
||||
_format_datetime_short,
|
||||
current_service,
|
||||
format_date_numeric,
|
||||
job_api_client,
|
||||
@@ -36,6 +42,7 @@ from app.utils import (
|
||||
get_help_argument,
|
||||
get_template,
|
||||
parse_filter_args,
|
||||
printing_today_or_tomorrow,
|
||||
set_status_filters,
|
||||
user_has_permissions,
|
||||
)
|
||||
@@ -76,6 +83,8 @@ def view_notification(service_id, notification_id):
|
||||
else:
|
||||
job = None
|
||||
|
||||
letter_print_day = get_letter_printing_statement(notification['status'], notification['created_at'])
|
||||
|
||||
return render_template(
|
||||
'views/notifications/notification.html',
|
||||
finished=(notification['status'] in (DELIVERED_STATUSES + FAILURE_STATUSES)),
|
||||
@@ -102,10 +111,23 @@ def view_notification(service_id, notification_id):
|
||||
notification_id=notification['id'],
|
||||
postage=notification['postage'],
|
||||
can_receive_inbound=(current_service.has_permission('inbound_sms')),
|
||||
is_precompiled_letter=notification['template']['is_precompiled_letter']
|
||||
is_precompiled_letter=notification['template']['is_precompiled_letter'],
|
||||
letter_print_day=letter_print_day
|
||||
)
|
||||
|
||||
|
||||
def get_letter_printing_statement(status, created_at):
|
||||
created_at_dt = parser.parse(created_at).replace(tzinfo=None)
|
||||
|
||||
if letter_can_be_cancelled(status, created_at_dt):
|
||||
return 'Printing starts {} at 5.30pm'.format(printing_today_or_tomorrow())
|
||||
else:
|
||||
printed_datetime = utc_string_to_aware_gmt_datetime(created_at) + timedelta(hours=6, minutes=30)
|
||||
printed_date = _format_datetime_short(printed_datetime)
|
||||
|
||||
return 'Printed on {}'.format(printed_date)
|
||||
|
||||
|
||||
def get_preview_error_image():
|
||||
path = os.path.join(os.path.dirname(__file__), "..", "..", "static", "images", "preview_error.png")
|
||||
with open(path, "rb") as file:
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</h1>
|
||||
|
||||
{% if just_sent %}
|
||||
{{ banner('We’ve started printing your letters', type='default', with_tick=True) }}
|
||||
{{ banner(just_sent_message, type='default', with_tick=True) }}
|
||||
{% else %}
|
||||
{{ ajax_block(partials, updates_url, 'status', finished=finished) }}
|
||||
{% endif %}
|
||||
|
||||
@@ -19,14 +19,16 @@
|
||||
Provided as PDF, sent
|
||||
{% else %}
|
||||
{% if help %}
|
||||
{{ template.name }}
|
||||
‘{{ template.name }}’
|
||||
{% else %}
|
||||
<a href="{{ url_for('.view_template', service_id=current_service.id, template_id=template.id) }}">{{ template.name }}</a>
|
||||
<a href="{{ url_for('.view_template', service_id=current_service.id, template_id=template.id) }}">‘{{ template.name }}’</a>
|
||||
{% endif %}
|
||||
sent
|
||||
was sent
|
||||
{% endif %}
|
||||
{% if job and job.original_file_name != 'Report' %}
|
||||
from
|
||||
{% set destination =
|
||||
{'letter': 'an address', 'email': 'an email address', 'sms': 'a phone number'} %}
|
||||
to {{ destination[template.template_type] }} from
|
||||
<a href="{{ url_for('.view_job', service_id=current_service.id, job_id=job.id) }}">{{ job.original_file_name }}</a>
|
||||
{% elif created_by %}
|
||||
by {{ created_by.name }}
|
||||
@@ -45,6 +47,9 @@
|
||||
(letter has content outside the printable area)
|
||||
</p>
|
||||
{% else %}
|
||||
<p>
|
||||
{{ letter_print_day }}
|
||||
</p>
|
||||
<p>
|
||||
Postage: {{ postage }} class
|
||||
</p>
|
||||
|
||||
13
app/utils.py
13
app/utils.py
@@ -2,7 +2,7 @@ import csv
|
||||
import os
|
||||
import re
|
||||
import unicodedata
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from datetime import datetime, time, timedelta, timezone
|
||||
from functools import wraps
|
||||
from io import StringIO
|
||||
from itertools import chain
|
||||
@@ -33,6 +33,7 @@ from notifications_utils.template import (
|
||||
LetterPreviewTemplate,
|
||||
SMSPreviewTemplate,
|
||||
)
|
||||
from notifications_utils.timezones import convert_utc_to_bst
|
||||
from orderedset._orderedset import OrderedSet
|
||||
from werkzeug.datastructures import MultiDict
|
||||
|
||||
@@ -643,3 +644,13 @@ def get_default_sms_sender(sms_senders):
|
||||
Field(x['sms_sender'], html='escape')
|
||||
for x in sms_senders if x['is_default']
|
||||
), "None"))
|
||||
|
||||
|
||||
def printing_today_or_tomorrow():
|
||||
now_utc = datetime.utcnow()
|
||||
now_bst = convert_utc_to_bst(now_utc)
|
||||
|
||||
if now_bst.time() < time(17, 30):
|
||||
return 'today'
|
||||
else:
|
||||
return 'tomorrow'
|
||||
|
||||
@@ -343,8 +343,8 @@ def test_should_show_letter_job(
|
||||
)
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 11:09:00.061258")
|
||||
def test_should_show_letter_job_with_banner_after_sending(
|
||||
@freeze_time("2016-01-01 11:09:00")
|
||||
def test_should_show_letter_job_with_banner_after_sending_before_1730(
|
||||
client_request,
|
||||
mock_get_service_letter_template,
|
||||
mock_get_job,
|
||||
@@ -362,7 +362,53 @@ def test_should_show_letter_job_with_banner_after_sending(
|
||||
|
||||
assert page.select('p.bottom-gutter') == []
|
||||
assert normalize_spaces(page.select('.banner-default-with-tick')[0].text) == (
|
||||
'We’ve started printing your letters'
|
||||
'Your letter has been sent. Printing starts today at 5.30pm.'
|
||||
)
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 11:09:00")
|
||||
def test_should_show_letter_job_with_banner_when_there_are_multiple_CSV_rows(
|
||||
client_request,
|
||||
mock_get_service_letter_template,
|
||||
mock_get_job_in_progress,
|
||||
mock_get_notifications,
|
||||
mock_get_service_data_retention_by_notification_type,
|
||||
fake_uuid,
|
||||
):
|
||||
|
||||
page = client_request.get(
|
||||
'main.view_job',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
job_id=fake_uuid,
|
||||
just_sent='yes',
|
||||
)
|
||||
|
||||
assert page.select('p.bottom-gutter') == []
|
||||
assert normalize_spaces(page.select('.banner-default-with-tick')[0].text) == (
|
||||
'Your letters have been sent. Printing starts today at 5.30pm.'
|
||||
)
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 18:09:00")
|
||||
def test_should_show_letter_job_with_banner_after_sending_after_1730(
|
||||
client_request,
|
||||
mock_get_service_letter_template,
|
||||
mock_get_job,
|
||||
mock_get_notifications,
|
||||
mock_get_service_data_retention_by_notification_type,
|
||||
fake_uuid,
|
||||
):
|
||||
|
||||
page = client_request.get(
|
||||
'main.view_job',
|
||||
service_id=SERVICE_ONE_ID,
|
||||
job_id=fake_uuid,
|
||||
just_sent='yes',
|
||||
)
|
||||
|
||||
assert page.select('p.bottom-gutter') == []
|
||||
assert normalize_spaces(page.select('.banner-default-with-tick')[0].text) == (
|
||||
'Your letter has been sent. Printing starts tomorrow at 5.30pm.'
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import base64
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
from unittest.mock import mock_open
|
||||
|
||||
@@ -7,6 +8,7 @@ from flask import url_for
|
||||
from freezegun import freeze_time
|
||||
from notifications_python_client.errors import APIError
|
||||
|
||||
from app.main.views.notifications import get_letter_printing_statement
|
||||
from tests.conftest import (
|
||||
SERVICE_ONE_ID,
|
||||
active_caseworking_user,
|
||||
@@ -127,7 +129,7 @@ def test_notification_page_doesnt_link_to_template_in_tour(
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(1)')[0].text) == (
|
||||
'sample template sent by Test User on 1 January at 1:01am'
|
||||
"‘sample template’ was sent by Test User on 1 January at 1:01am"
|
||||
)
|
||||
assert len(page.select('main p:nth-of-type(1) a')) == 0
|
||||
|
||||
@@ -141,7 +143,14 @@ def test_notification_page_shows_page_for_letter_notification(
|
||||
|
||||
count_of_pages = 3
|
||||
|
||||
mock_get_notification(mocker, fake_uuid, template_type='letter', postage='second')
|
||||
notification = mock_get_notification(
|
||||
mocker,
|
||||
fake_uuid,
|
||||
notification_status='created',
|
||||
template_type='letter',
|
||||
postage='second')
|
||||
notification.created_at = datetime.utcnow()
|
||||
|
||||
mock_page_count = mocker.patch(
|
||||
'app.main.views.notifications.get_page_count_for_letter',
|
||||
return_value=count_of_pages
|
||||
@@ -154,12 +163,15 @@ def test_notification_page_shows_page_for_letter_notification(
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(1)')[0].text) == (
|
||||
'sample template sent by Test User on 1 January at 1:01am'
|
||||
"‘sample template’ was sent by Test User on 1 January at 1:01am"
|
||||
)
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(2)')[0].text) == (
|
||||
'Postage: second class'
|
||||
'Printing starts today at 5.30pm'
|
||||
)
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(3)')[0].text) == (
|
||||
'Postage: second class'
|
||||
)
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(4)')[0].text) == (
|
||||
'Estimated delivery date: 6 January'
|
||||
)
|
||||
assert page.select('p.notification-status') == []
|
||||
@@ -215,7 +227,7 @@ def test_notification_page_shows_cancelled_letter(
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select('main p')[0].text) == (
|
||||
'sample template sent by Test User on 1 January at 1:01am'
|
||||
"‘sample template’ was sent by Test User on 1 January at 1:01am"
|
||||
)
|
||||
assert normalize_spaces(page.select('main p')[1].text) == (
|
||||
expected_message
|
||||
@@ -225,13 +237,18 @@ def test_notification_page_shows_cancelled_letter(
|
||||
assert page.select_one('main img')['src'].endswith('.png?page=1')
|
||||
|
||||
|
||||
@freeze_time("2016-01-01 01:01")
|
||||
@freeze_time("2016-01-01 18:00")
|
||||
def test_notification_page_shows_page_for_first_class_letter_notification(
|
||||
client_request,
|
||||
mocker,
|
||||
fake_uuid,
|
||||
):
|
||||
mock_get_notification(mocker, fake_uuid, template_type='letter', postage='first')
|
||||
mock_get_notification(
|
||||
mocker,
|
||||
fake_uuid,
|
||||
notification_status='pending-virus-check',
|
||||
template_type='letter',
|
||||
postage='first')
|
||||
mocker.patch('app.main.views.notifications.get_page_count_for_letter', return_value=3)
|
||||
|
||||
page = client_request.get(
|
||||
@@ -240,8 +257,9 @@ def test_notification_page_shows_page_for_first_class_letter_notification(
|
||||
notification_id=fake_uuid,
|
||||
)
|
||||
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(2)')[0].text) == 'Postage: first class'
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(3)')[0].text) == 'Estimated delivery date: 5 January'
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(2)')[0].text) == 'Printing starts tomorrow at 5.30pm'
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(3)')[0].text) == 'Postage: first class'
|
||||
assert normalize_spaces(page.select('main p:nth-of-type(4)')[0].text) == 'Estimated delivery date: 5 January'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('filetype', [
|
||||
@@ -473,3 +491,39 @@ def test_should_show_image_of_precompiled_letter_notification(
|
||||
assert response.status_code == 200
|
||||
assert response.get_data(as_text=True) == 'foo'
|
||||
assert mock_pdf_page_count.called_once()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('created_at, current_datetime', [
|
||||
('2017-07-07T12:00:00+00:00', '2017-07-07 16:29:00'), # created today, summer
|
||||
('2017-12-12T12:00:00+00:00', '2017-12-12 17:29:00'), # created today, winter
|
||||
('2017-12-12T21:30:00+00:00', '2017-12-13 17:29:00'), # created after 5.30 yesterday
|
||||
('2017-03-25T17:30:00+00:00', '2017-03-26 16:29:00'), # over clock change period on 2017-03-26
|
||||
])
|
||||
def test_get_letter_printing_statement_when_letter_prints_today(created_at, current_datetime):
|
||||
with freeze_time(current_datetime):
|
||||
statement = get_letter_printing_statement('created', created_at)
|
||||
|
||||
assert statement == 'Printing starts today at 5.30pm'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('created_at, current_datetime', [
|
||||
('2017-07-07T16:31:00+00:00', '2017-07-07 22:59:00'), # created today, summer
|
||||
('2017-12-12T17:31:00+00:00', '2017-12-12 23:59:00'), # created today, winter
|
||||
])
|
||||
def test_get_letter_printing_statement_when_letter_prints_tomorrow(created_at, current_datetime):
|
||||
with freeze_time(current_datetime):
|
||||
statement = get_letter_printing_statement('created', created_at)
|
||||
|
||||
assert statement == 'Printing starts tomorrow at 5.30pm'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('created_at, print_day', [
|
||||
('2017-07-06T16:30:00+00:00', '7 July'),
|
||||
('2017-12-01T00:00:00+00:00', '1 December'),
|
||||
('2017-03-26T12:00:00+00:00', '26 March'),
|
||||
])
|
||||
@freeze_time('2017-07-07 12:00:00')
|
||||
def test_get_letter_printing_statement_for_letter_that_has_been_sent(created_at, print_day):
|
||||
statement = get_letter_printing_statement('delivered', created_at)
|
||||
|
||||
assert statement == 'Printed on {}'.format(print_day)
|
||||
|
||||
@@ -17,6 +17,7 @@ from app.utils import (
|
||||
generate_notifications_csv,
|
||||
generate_previous_dict,
|
||||
get_logo_cdn_domain,
|
||||
printing_today_or_tomorrow,
|
||||
)
|
||||
from tests.conftest import fake_uuid
|
||||
|
||||
@@ -452,3 +453,27 @@ def test_validate_email_domain_data():
|
||||
def test_format_datetime_relative(time, human_readable_datetime):
|
||||
with freeze_time('2018-03-21 12:00'):
|
||||
assert format_datetime_relative(time) == human_readable_datetime
|
||||
|
||||
|
||||
@pytest.mark.parametrize('utc_datetime', [
|
||||
'2018-08-01 23:00',
|
||||
'2018-08-01 16:29',
|
||||
'2018-11-01 00:00',
|
||||
'2018-11-01 10:00',
|
||||
'2018-11-01 17:29',
|
||||
])
|
||||
def test_printing_today_or_tomorrow_returns_today(utc_datetime):
|
||||
with freeze_time(utc_datetime):
|
||||
assert printing_today_or_tomorrow() == 'today'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('datetime', [
|
||||
'2018-08-01 22:59',
|
||||
'2018-08-01 16:30',
|
||||
'2018-11-01 17:30',
|
||||
'2018-11-01 21:00',
|
||||
'2018-11-01 23:59',
|
||||
])
|
||||
def test_printing_today_or_tomorrow_returns_tomorrow(datetime):
|
||||
with freeze_time(datetime):
|
||||
assert printing_today_or_tomorrow() == 'tomorrow'
|
||||
|
||||
Reference in New Issue
Block a user