mirror of
https://github.com/GSA/notifications-api.git
synced 2025-12-23 17:01:35 -05:00
Some teams have started uploading quite a lot of letters (in the hundreds per week). They’re also uploading CSVs of emails. This means the uploads page ends up quite jumbled. This is because: - there’s just a lot of items to scan through - conceptually it’s a bit odd to have batches of things displayed alongside individual things on the same page So instead this commit starts grouping together uploaded letters. It does this by the date on which we ‘start’ printing them, or in other words the time at which they can no longer be cancelled. This feels like a natural grouping, and it matches what we know about people’s mental models of ‘batches’ and ‘runs’ when talking about printing. The code for this is a bit gnarly because: - timezones - the print cutoff doesn’t align with the end of a day - we have to do this in SQL because it wouldn’t be efficient to query thousands of letters and then do the timezone calculations on them in Python
174 lines
8.0 KiB
Python
174 lines
8.0 KiB
Python
from datetime import datetime, timedelta, date
|
|
|
|
from freezegun import freeze_time
|
|
|
|
from app.models import LETTER_TYPE, JOB_STATUS_FINISHED, JOB_STATUS_PENDING
|
|
from tests.app.db import create_job, create_notification, create_template, create_ft_notification_status
|
|
from tests.conftest import set_config
|
|
|
|
|
|
def create_uploaded_letter(letter_template, service, status='created', created_at=None):
|
|
return create_notification(
|
|
template=letter_template,
|
|
to_field="742 Evergreen Terrace",
|
|
status=status,
|
|
reference="dvla-reference",
|
|
client_reference="file-name",
|
|
one_off=True,
|
|
created_by_id=service.users[0].id,
|
|
created_at=created_at
|
|
)
|
|
|
|
|
|
def create_precompiled_template(service):
|
|
return create_template(
|
|
service,
|
|
template_type=LETTER_TYPE,
|
|
template_name='Pre-compiled PDF',
|
|
subject='Pre-compiled PDF',
|
|
content="",
|
|
hidden=True,
|
|
postage="second",
|
|
)
|
|
|
|
|
|
@freeze_time('2020-02-02 14:00')
|
|
def test_get_uploads(admin_request, sample_template):
|
|
letter_template = create_precompiled_template(sample_template.service)
|
|
|
|
create_uploaded_letter(letter_template, sample_template.service, status='delivered',
|
|
created_at=datetime.utcnow() - timedelta(minutes=4))
|
|
upload_2 = create_job(template=sample_template,
|
|
processing_started=datetime.utcnow() - timedelta(minutes=3),
|
|
job_status=JOB_STATUS_FINISHED)
|
|
create_uploaded_letter(letter_template, sample_template.service, status='delivered',
|
|
created_at=datetime.utcnow() - timedelta(minutes=2))
|
|
upload_4 = create_job(template=sample_template,
|
|
processing_started=datetime.utcnow() - timedelta(minutes=1),
|
|
job_status=JOB_STATUS_FINISHED)
|
|
upload_5 = create_job(template=sample_template, processing_started=None,
|
|
job_status=JOB_STATUS_PENDING, notification_count=10)
|
|
|
|
service_id = sample_template.service.id
|
|
|
|
resp_json = admin_request.get('upload.get_uploads_by_service', service_id=service_id)
|
|
data = resp_json['data']
|
|
assert len(data) == 4
|
|
assert data[0] == {'id': str(upload_5.id),
|
|
'original_file_name': 'some.csv',
|
|
'recipient': None,
|
|
'notification_count': 10,
|
|
'template_type': 'sms',
|
|
'created_at': upload_5.created_at.strftime("%Y-%m-%d %H:%M:%S"),
|
|
'statistics': [],
|
|
'upload_type': 'job'}
|
|
assert data[1] == {'id': None,
|
|
'original_file_name': 'Uploaded letters',
|
|
'recipient': None,
|
|
'notification_count': 2,
|
|
'template_type': 'letter',
|
|
'created_at': upload_4.created_at.replace(hour=17, minute=30).strftime(
|
|
"%Y-%m-%d %H:%M:%S"),
|
|
'statistics': [],
|
|
'upload_type': 'letter_day'}
|
|
assert data[3] == {'id': str(upload_2.id),
|
|
'original_file_name': "some.csv",
|
|
'recipient': None,
|
|
'notification_count': 1,
|
|
'template_type': 'sms',
|
|
'created_at': upload_2.created_at.strftime(
|
|
"%Y-%m-%d %H:%M:%S"),
|
|
'statistics': [],
|
|
'upload_type': 'job'}
|
|
|
|
|
|
def test_get_uploads_should_return_statistics(admin_request, sample_template):
|
|
now = datetime.utcnow()
|
|
earlier = datetime.utcnow() - timedelta(days=1)
|
|
job_1 = create_job(template=sample_template, job_status='pending')
|
|
job_2 = create_job(sample_template, processing_started=earlier)
|
|
for _ in range(3):
|
|
create_notification(template=sample_template, job=job_2, status='created')
|
|
|
|
job_3 = create_job(sample_template, processing_started=now)
|
|
for _ in range(4):
|
|
create_notification(template=sample_template, job=job_3, status='sending')
|
|
|
|
letter_template = create_precompiled_template(sample_template.service)
|
|
create_uploaded_letter(letter_template, sample_template.service, status='delivered',
|
|
created_at=datetime.utcnow() - timedelta(days=3))
|
|
|
|
resp_json = admin_request.get('upload.get_uploads_by_service', service_id=sample_template.service_id)['data']
|
|
assert len(resp_json) == 4
|
|
assert resp_json[0]['id'] == str(job_1.id)
|
|
assert resp_json[0]['statistics'] == []
|
|
assert resp_json[1]['id'] == str(job_3.id)
|
|
assert resp_json[1]['statistics'] == [{'status': 'sending', 'count': 4}]
|
|
assert resp_json[2]['id'] == str(job_2.id)
|
|
assert resp_json[2]['statistics'] == [{'status': 'created', 'count': 3}]
|
|
assert resp_json[3]['id'] is None
|
|
assert resp_json[3]['statistics'] == []
|
|
|
|
|
|
def test_get_uploads_should_paginate(admin_request, sample_template):
|
|
for _ in range(10):
|
|
create_job(sample_template)
|
|
|
|
with set_config(admin_request.app, 'PAGE_SIZE', 2):
|
|
resp_json = admin_request.get('upload.get_uploads_by_service', service_id=sample_template.service_id)
|
|
|
|
assert len(resp_json['data']) == 2
|
|
assert resp_json['page_size'] == 2
|
|
assert resp_json['total'] == 10
|
|
assert 'links' in resp_json
|
|
assert set(resp_json['links'].keys()) == {'next', 'last'}
|
|
|
|
|
|
def test_get_uploads_accepts_page_parameter(admin_request, sample_template):
|
|
for _ in range(10):
|
|
create_job(sample_template)
|
|
|
|
with set_config(admin_request.app, 'PAGE_SIZE', 2):
|
|
resp_json = admin_request.get('upload.get_uploads_by_service', service_id=sample_template.service_id, page=2)
|
|
|
|
assert len(resp_json['data']) == 2
|
|
assert resp_json['page_size'] == 2
|
|
assert resp_json['total'] == 10
|
|
assert 'links' in resp_json
|
|
assert set(resp_json['links'].keys()) == {'prev', 'next', 'last'}
|
|
|
|
|
|
@freeze_time('2017-06-10 12:00')
|
|
def test_get_uploads_should_retrieve_from_ft_notification_status_for_old_jobs(admin_request, sample_template):
|
|
# it's the 10th today, so 3 days should include all of 7th, 8th, 9th, and some of 10th.
|
|
just_three_days_ago = datetime(2017, 6, 6, 22, 59, 59)
|
|
not_quite_three_days_ago = just_three_days_ago + timedelta(seconds=1)
|
|
|
|
job_1 = create_job(sample_template, created_at=just_three_days_ago, processing_started=just_three_days_ago)
|
|
job_2 = create_job(sample_template, created_at=just_three_days_ago, processing_started=not_quite_three_days_ago)
|
|
# is old but hasn't started yet (probably a scheduled job). We don't have any stats for this job yet.
|
|
job_3 = create_job(sample_template, created_at=just_three_days_ago, processing_started=None)
|
|
|
|
# some notifications created more than three days ago, some created after the midnight cutoff
|
|
create_ft_notification_status(date(2017, 6, 6), job=job_1, notification_status='delivered', count=2)
|
|
create_ft_notification_status(date(2017, 6, 7), job=job_1, notification_status='delivered', count=4)
|
|
# job2's new enough
|
|
create_notification(job=job_2, status='created', created_at=not_quite_three_days_ago)
|
|
|
|
# this isn't picked up because the job is too new
|
|
create_ft_notification_status(date(2017, 6, 7), job=job_2, notification_status='delivered', count=8)
|
|
# this isn't picked up - while the job is old, it started in last 3 days so we look at notification table instead
|
|
create_ft_notification_status(date(2017, 6, 7), job=job_3, notification_status='delivered', count=16)
|
|
|
|
# this isn't picked up because we're using the ft status table for job_1 as it's old
|
|
create_notification(job=job_1, status='created', created_at=not_quite_three_days_ago)
|
|
|
|
resp_json = admin_request.get('upload.get_uploads_by_service', service_id=sample_template.service_id)['data']
|
|
|
|
assert resp_json[0]['id'] == str(job_3.id)
|
|
assert resp_json[0]['statistics'] == []
|
|
assert resp_json[1]['id'] == str(job_2.id)
|
|
assert resp_json[1]['statistics'] == [{'status': 'created', 'count': 1}]
|
|
assert resp_json[2]['id'] == str(job_1.id)
|
|
assert resp_json[2]['statistics'] == [{'status': 'delivered', 'count': 6}]
|