From 9fbd43c0727d44c8703ed4ca3e09cf0dff28ef5f Mon Sep 17 00:00:00 2001 From: Imdad Ahad Date: Thu, 20 Apr 2017 11:52:00 +0100 Subject: [PATCH] Serialise notifications for csv separately: * Introduces separate method on Notification to serialise the notification * ready for csv output * Fixes issue where job_row_number = 0 not being accounted for correctly --- app/models.py | 49 +++++++++++++++++++- tests/app/conftest.py | 5 +-- tests/app/test_model.py | 99 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 4 deletions(-) diff --git a/app/models.py b/app/models.py index f829ca429..fa3fb3779 100644 --- a/app/models.py +++ b/app/models.py @@ -1,3 +1,4 @@ +import time import uuid import datetime from flask import url_for @@ -27,6 +28,7 @@ from app import ( ) from app.history_meta import Versioned +from app.utils import get_utc_time_in_bst def filter_null_value_fields(obj): @@ -709,8 +711,53 @@ class Notification(db.Model): template_object = get_template_instance(self.template.__dict__, self.personalisation) return template_object.subject - def serialize(self): + @property + def formatted_status(self): + return { + 'email': { + 'failed': 'Failed', + 'technical-failure': 'Technical failure', + 'temporary-failure': 'Inbox not accepting messages right now', + 'permanent-failure': 'Email address doesn’t exist', + 'delivered': 'Delivered', + 'sending': 'Sending', + 'created': 'Sending' + }, + 'sms': { + 'failed': 'Failed', + 'technical-failure': 'Technical failure', + 'temporary-failure': 'Phone not accepting messages right now', + 'permanent-failure': 'Phone number doesn’t exist', + 'delivered': 'Delivered', + 'sending': 'Sending', + 'created': 'Sending' + }, + 'letter': { + 'failed': 'Failed', + 'technical-failure': 'Technical failure', + 'temporary-failure': 'Temporary failure', + 'permanent-failure': 'Permanent failure', + 'delivered': 'Delivered', + 'sending': 'Sending', + 'created': 'Sending' + } + }[self.template.template_type].get(self.status, self.status) + def serialize_for_csv(self): + created_at_in_bst = get_utc_time_in_bst(self.created_at) + serialized = { + "row_number": '' if self.job_row_number is None else self.job_row_number + 1, + "recipient": self.to, + "template_name": self.template.name, + "template_type": self.template.template_type, + "job_name": self.job.original_file_name if self.job else '', + "status": self.formatted_status, + "created_at": time.strftime('%A %d %B %Y at %H:%M', created_at_in_bst.timetuple()) + } + + return serialized + + def serialize(self): template_dict = { 'version': self.template.version, 'id': self.template.id, diff --git a/tests/app/conftest.py b/tests/app/conftest.py index 0805242b7..fab72ae7e 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -405,14 +405,13 @@ def sample_notification_with_job( ): if job is None: job = sample_job(notify_db, notify_db_session, service=service, template=template) - return sample_notification( notify_db, notify_db_session, service, template, job=job, - job_row_number=job_row_number if job_row_number else None, + job_row_number=job_row_number if job_row_number is not None else None, to_field=to_field, status=status, reference=reference, @@ -482,7 +481,7 @@ def sample_notification( 'updated_at': created_at if status in NOTIFICATION_STATUS_TYPES_COMPLETED else None, 'client_reference': client_reference } - if job_row_number: + if job_row_number is not None: data['job_row_number'] = job_row_number notification = Notification(**data) dao_create_notification(notification) diff --git a/tests/app/test_model.py b/tests/app/test_model.py index 21b3df4cc..67b80edfa 100644 --- a/tests/app/test_model.py +++ b/tests/app/test_model.py @@ -1,5 +1,7 @@ import pytest +from freezegun import freeze_time + from app.models import ( ServiceWhitelist, Notification, @@ -11,6 +13,10 @@ from app.models import ( NOTIFICATION_TECHNICAL_FAILURE, NOTIFICATION_STATUS_TYPES_FAILED ) +from tests.app.conftest import ( + sample_template as create_sample_template, + sample_notification_with_job as create_sample_notification_with_job +) @pytest.mark.parametrize('mobile_number', [ @@ -65,3 +71,96 @@ def test_status_conversion_handles_failed_statuses(initial_statuses, expected_st converted_statuses = Notification.substitute_status(initial_statuses) assert len(converted_statuses) == len(expected_statuses) assert set(converted_statuses) == set(expected_statuses) + + +@freeze_time("2016-01-01 11:09:00.000000") +@pytest.mark.parametrize('template_type, recipient', [ + ('sms', '+447700900855'), + ('email', 'foo@bar.com'), +]) +def test_notification_for_csv_returns_correct_type(notify_db, notify_db_session, template_type, recipient): + template = create_sample_template(notify_db, notify_db_session, template_type=template_type) + notification = create_sample_notification_with_job( + notify_db, + notify_db_session, + template=template, + to_field=recipient + ) + + expected_resp = { + "recipient": recipient, + "row_number": "", + "template_name": "Template Name", + "template_type": template_type, + "created_at": "Friday 01 January 2016 at 11:09", + "job_name": "some.csv", + "status": "Sending" + } + + serialized = notification.serialize_for_csv() + assert serialized == expected_resp + + +@freeze_time("2016-01-01 11:09:00.000000") +def test_notification_for_csv_returns_correct_job_row_number(notify_db, notify_db_session): + notification = create_sample_notification_with_job( + notify_db, + notify_db_session, + job_row_number=0 + ) + expected_resp = { + "recipient": "+447700900855", + "row_number": 1, + "template_name": "Template Name", + "template_type": "sms", + "created_at": "Friday 01 January 2016 at 11:09", + "job_name": "some.csv", + "status": "Sending" + } + + serialized = notification.serialize_for_csv() + assert serialized == expected_resp + + +@freeze_time("2016-01-30 12:39:58.321312") +def test_notifiation_for_csv_returns_formatted_status(notify_db, notify_db_session): + notification = create_sample_notification_with_job( + notify_db, + notify_db_session, + job_row_number=51, + status='temporary-failure' + ) + expected_resp = { + "recipient": "+447700900855", + "row_number": 52, + "template_name": "Template Name", + "template_type": "sms", + "created_at": "Saturday 30 January 2016 at 12:39", + "job_name": "some.csv", + "status": "Phone not accepting messages right now" + } + + serialized = notification.serialize_for_csv() + assert serialized == expected_resp + + +@freeze_time("2017-03-26 23:01:53.321312") +def test_notifiation_for_csv_returns_bst_correctly(notify_db, notify_db_session): + notification = create_sample_notification_with_job( + notify_db, + notify_db_session, + job_row_number=100, + status='permanent-failure' + ) + expected_resp = { + "recipient": "+447700900855", + "row_number": 101, + "template_name": "Template Name", + "template_type": "sms", + "created_at": "Monday 27 March 2017 at 00:01", + "job_name": "some.csv", + "status": "Phone number doesn’t exist" + } + + serialized = notification.serialize_for_csv() + assert serialized == expected_resp