From 40a0c6292690eda9cf53ff7c0bba4dfc645fa664 Mon Sep 17 00:00:00 2001 From: Rebecca Law Date: Mon, 9 Dec 2019 17:27:18 +0000 Subject: [PATCH] New endpoint to return a summary of returned letters for the service. --- app/dao/returned_letters_dao.py | 33 +++++++++++++------ app/service/rest.py | 10 ++++++ tests/app/dao/test_returned_letters_dao.py | 37 ++++++++++++++++++++-- tests/app/db.py | 20 +++++++++++- 4 files changed, 87 insertions(+), 13 deletions(-) diff --git a/app/dao/returned_letters_dao.py b/app/dao/returned_letters_dao.py index 24d8ae438..48e121ce0 100644 --- a/app/dao/returned_letters_dao.py +++ b/app/dao/returned_letters_dao.py @@ -1,5 +1,6 @@ from datetime import datetime +from sqlalchemy import func, desc from sqlalchemy.dialects.postgresql import insert from app import db @@ -7,6 +8,19 @@ from app.dao.dao_utils import transactional from app.models import Notification, NotificationHistory, ReturnedLetter + +def _get_notification_ids_for_references(references): + notification_ids = db.session.query(Notification.id, Notification.service_id).filter( + Notification.reference.in_(references) + ).all() + + notification_history_ids = db.session.query(NotificationHistory.id, NotificationHistory.service_id).filter( + NotificationHistory.reference.in_(references) + ).all() + + return notification_ids + notification_history_ids + + @transactional def insert_or_update_returned_letters(references): data = _get_notification_ids_for_references(references) @@ -28,13 +42,14 @@ def insert_or_update_returned_letters(references): db.session.connection().execute(stmt) -def _get_notification_ids_for_references(references): - notification_ids = db.session.query(Notification.id, Notification.service_id).filter( - Notification.reference.in_(references) +def get_returned_letter_summary(service_id): + return db.session.query( + func.count(ReturnedLetter.notification_id).label('returned_letter_count'), + ReturnedLetter.reported_at + ).filter( + ReturnedLetter.service_id == service_id, + ).group_by( + ReturnedLetter.reported_at + ).order_by( + desc(ReturnedLetter.reported_at) ).all() - - notification_history_ids = db.session.query(NotificationHistory.id, NotificationHistory.service_id).filter( - NotificationHistory.reference.in_(references) - ).all() - - return notification_ids + notification_history_ids diff --git a/app/service/rest.py b/app/service/rest.py index 60141e87e..e34f90e26 100644 --- a/app/service/rest.py +++ b/app/service/rest.py @@ -29,6 +29,7 @@ from app.dao.fact_notification_status_dao import ( ) from app.dao.inbound_numbers_dao import dao_allocate_number_for_service from app.dao.organisation_dao import dao_get_organisation_by_service_id +from app.dao.returned_letters_dao import get_returned_letter_summary from app.dao.service_data_retention_dao import ( fetch_service_data_retention, fetch_service_data_retention_by_id, @@ -939,3 +940,12 @@ def check_if_reply_to_address_already_in_use(service_id, email_address): raise InvalidRequest( "Your service already uses ‘{}’ as an email reply-to address.".format(email_address), status_code=400 ) + + +@service_blueprint.route('/returned-letter-summary') +def returned_letter_summary(service_id): + results = get_returned_letter_summary(service_id) + + json_results = [{'returned_letter_count': x.returned_letter_count, 'reported_at': x.reported_at} for x in results] + + return jsonify(json_results) diff --git a/tests/app/dao/test_returned_letters_dao.py b/tests/app/dao/test_returned_letters_dao.py index 1a94f1fde..bb0836be0 100644 --- a/tests/app/dao/test_returned_letters_dao.py +++ b/tests/app/dao/test_returned_letters_dao.py @@ -1,10 +1,10 @@ -from datetime import datetime +from datetime import datetime, timedelta from freezegun import freeze_time -from app.dao.returned_letters_dao import insert_or_update_returned_letters +from app.dao.returned_letters_dao import insert_or_update_returned_letters, get_returned_letter_summary from app.models import ReturnedLetter -from tests.app.db import create_notification, create_notification_history +from tests.app.db import create_notification, create_notification_history, create_returned_letter def test_insert_or_update_returned_letters_inserts(sample_letter_template): @@ -81,3 +81,34 @@ def test_insert_or_update_returned_letters_with_duplicates_in_reference_list(sam assert len(returned_letters) == 2 for x in returned_letters: assert x.notification_id in [notification_1.id, notification_2.id] + + +def test_get_returned_letter_summary(sample_service): + now = datetime.utcnow() + create_returned_letter(sample_service, reported_at=now) + create_returned_letter(sample_service, reported_at=now) + + results = get_returned_letter_summary(sample_service.id) + + assert len(results) == 1 + + assert results[0].returned_letter_count == 2 + assert results[0].reported_at == now + + +def test_get_returned_letter_summary_orders_by_reported_at(sample_service): + now = datetime.utcnow() + last_month = datetime.utcnow() - timedelta(days=30) + create_returned_letter(sample_service, reported_at=now) + create_returned_letter(sample_service, reported_at=now) + create_returned_letter(sample_service, reported_at=now) + create_returned_letter(sample_service, reported_at=last_month) + create_returned_letter(sample_service, reported_at=last_month) + + results = get_returned_letter_summary(sample_service.id) + + assert len(results) == 2 + assert results[0].reported_at == now + assert results[0].returned_letter_count == 3 + assert results[1].reported_at == last_month + assert results[1].returned_letter_count == 2 diff --git a/tests/app/db.py b/tests/app/db.py index 4cbcfdfc2..50840bf2c 100644 --- a/tests/app/db.py +++ b/tests/app/db.py @@ -59,7 +59,9 @@ from app.models import ( TemplateFolder, LetterBranding, Domain, - NotificationHistory + NotificationHistory, + NOTIFICATION_RETURNED_LETTER, + ReturnedLetter ) @@ -940,3 +942,19 @@ def set_up_usage_data(start_date): notifications_sent=15, billable_unit=4, rate=.55, postage='second') return org, org_3, service, service_3, service_4, service_sms_only + + +def create_returned_letter(service, reported_at=None): + if not service: + service = create_service(service_name='a - with sms and letter') + template = create_template(service=service, template_type=LETTER_TYPE) + notification = create_notification(template=template, status=NOTIFICATION_RETURNED_LETTER) + returned_letter = ReturnedLetter( + service_id= service.id, + reported_at= reported_at or datetime.utcnow(), + notification_id= notification.id + ) + + db.session.add(returned_letter) + db.session.commit() + return returned_letter \ No newline at end of file