diff --git a/app/dao/notifications_dao.py b/app/dao/notifications_dao.py index ab70f9673..ed84218d6 100644 --- a/app/dao/notifications_dao.py +++ b/app/dao/notifications_dao.py @@ -267,6 +267,29 @@ def get_notifications_for_job( return pagination +def get_recent_notifications_for_job( + service_id, job_id, filter_dict=None, page=1, page_size=None +): + if page_size is None: + page_size = current_app.config["PAGE_SIZE"] + + stmt = select(Notification).where( + Notification.service_id == service_id, + Notification.job_id == job_id, + ) + + stmt = _filter_query(stmt, filter_dict) + stmt = stmt.order_by(desc(Notification.job_row_number)) + results = db.session.execute(stmt).scalars().all() + + page_size = current_app.config["PAGE_SIZE"] + offset = (page - 1) * page_size + paginated_results = results[offset : offset + page_size] + + pagination = Pagination(paginated_results, page, page_size, len(results)) + return pagination + + def dao_get_notification_count_for_job_id(*, job_id): stmt = select(func.count(Notification.id)).where(Notification.job_id == job_id) return db.session.execute(stmt).scalar() diff --git a/app/job/rest.py b/app/job/rest.py index afc563514..ed506a5aa 100644 --- a/app/job/rest.py +++ b/app/job/rest.py @@ -23,6 +23,7 @@ from app.dao.jobs_dao import ( from app.dao.notifications_dao import ( dao_get_notification_count_for_job_id, get_notifications_for_job, + get_recent_notifications_for_job, ) from app.dao.services_dao import dao_fetch_service_by_id from app.dao.templates_dao import dao_get_template_by_id @@ -125,6 +126,71 @@ def get_all_notifications_for_service_job(service_id, job_id): ) +@job_blueprint.route("//recent_notifications", methods=["GET"]) +def get_recent_notifications_for_service_job(service_id, job_id): + data = notifications_filter_schema.load(request.args) + page = data["page"] if "page" in data else 1 + page_size = ( + data["page_size"] + if "page_size" in data + else current_app.config.get("PAGE_SIZE") + ) + paginated_notifications = get_recent_notifications_for_job( + service_id, + job_id, + filter_dict=data, + page=page, + page_size=page_size, + ) + + kwargs = request.args.to_dict() + kwargs["service_id"] = service_id + kwargs["job_id"] = job_id + + for notification in paginated_notifications.items: + if notification.job_id is not None: + recipient = get_phone_number_from_s3( + notification.service_id, + notification.job_id, + notification.job_row_number, + ) + notification.to = recipient + notification.normalised_to = recipient + + for notification in paginated_notifications.items: + if notification.job_id is not None: + notification.personalisation = get_personalisation_from_s3( + notification.service_id, + notification.job_id, + notification.job_row_number, + ) + + notifications = None + if data.get("format_for_csv"): + notifications = [ + notification.serialize_for_csv() + for notification in paginated_notifications.items + ] + else: + notifications = notification_with_template_schema.dump( + paginated_notifications.items, many=True + ) + + return ( + jsonify( + notifications=notifications, + page_size=page_size, + total=paginated_notifications.total, + links=pagination_links( + paginated_notifications, + ".get_all_notifications_for_service_job", + **kwargs, + ), + ), + 200, + ) + + @job_blueprint.route("//notification_count", methods=["GET"]) def get_notification_count_for_job_id(service_id, job_id): dao_get_job_by_service_id_and_job_id(service_id, job_id) diff --git a/tests/app/dao/notification_dao/test_notification_dao.py b/tests/app/dao/notification_dao/test_notification_dao.py index 1a145538a..a6748dd33 100644 --- a/tests/app/dao/notification_dao/test_notification_dao.py +++ b/tests/app/dao/notification_dao/test_notification_dao.py @@ -28,6 +28,7 @@ from app.dao.notifications_dao import ( get_notification_with_personalisation, get_notifications_for_job, get_notifications_for_service, + get_recent_notifications_for_job, get_service_ids_with_notifications_on_date, notifications_not_yet_sent, sanitize_successful_notification_by_id, @@ -692,6 +693,17 @@ def test_get_all_notifications_for_job(sample_job): assert len(notifications_from_db) == 5 +def test_get_recent_notifications_for_job(sample_job): + + for status in NotificationStatus: + create_notification(template=sample_job.template, job=sample_job, status=status) + + notifications_from_db = get_recent_notifications_for_job( + sample_job.service.id, sample_job.id + ).items + assert len(notifications_from_db) == 13 + + def test_get_all_notifications_for_job_by_status(sample_job): notifications = partial( get_notifications_for_job, sample_job.service.id, sample_job.id diff --git a/tests/app/job/test_rest.py b/tests/app/job/test_rest.py index b6d7a15e9..f65ce2458 100644 --- a/tests/app/job/test_rest.py +++ b/tests/app/job/test_rest.py @@ -488,6 +488,48 @@ def test_get_all_notifications_for_job_in_order_of_job_number( assert resp["notifications"][2]["job_row_number"] == notification_3.job_row_number +def test_get_recent_notifications_for_job_in_reverse_order_of_job_number( + admin_request, sample_template, mocker +): + mock_s3 = mocker.patch("app.job.rest.get_phone_number_from_s3") + mock_s3.return_value = "15555555555" + + mock_s3_personalisation = mocker.patch("app.job.rest.get_personalisation_from_s3") + mock_s3_personalisation.return_value = {} + + main_job = create_job(sample_template) + another_job = create_job(sample_template) + + count = 1 + for status in NotificationStatus: + create_notification(job=main_job, job_row_number=str(count), status=status) + count = count + 1 + create_notification(job=another_job) + + resp = admin_request.get( + "job.get_recent_notifications_for_service_job", + service_id=main_job.service_id, + job_id=main_job.id, + ) + + assert len(resp["notifications"]) == 13 + assert resp["notifications"][0]["status"] == "virus-scan-failed" + assert resp["notifications"][0]["job_row_number"] == 13 + + query_string = {"status": "delivered"} + resp = admin_request.get( + "job.get_recent_notifications_for_service_job", + service_id=main_job.service_id, + job_id=main_job.id, + **query_string, + ) + + assert len(resp["notifications"]) == 1 + + assert resp["notifications"][0]["status"] == "delivered" + assert resp["notifications"][0]["job_row_number"] == 5 + + @pytest.mark.parametrize( "expected_notification_count, status_args", [