From 9758b96a2bf032bb52985bb0a3540d6946e7a9fe Mon Sep 17 00:00:00 2001 From: Paul Craig Date: Fri, 18 Nov 2016 17:36:11 +0000 Subject: [PATCH] Create 'v2' get notification route The new 'v2' API wants to return less data than the previous one, which was sending back tons of fields the clients never used. This new route returns only useful information, with the JSON response dict being built up in the model's `.serialize()` method. Note that writing the test for this was a bit painful because of having to treat loads of keys differently. Hopefully we think this is a good way to write this test, because if we don't, we should start thinking of a better way to check the values are what we expect. --- app/__init__.py | 7 ++- app/models.py | 51 ++++++++++++++++++- app/v2/notifications/get_notifications.py | 10 +++- .../notifications/test_get_notifications.py | 46 +++++++++++++++++ .../test_notification_schemas.py | 5 +- 5 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 tests/app/v2/notifications/test_get_notifications.py diff --git a/app/__init__.py b/app/__init__.py index 165a8b884..e42bb7dc8 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -96,8 +96,11 @@ def register_blueprint(application): def register_v2_blueprints(application): - from app.v2.notifications.post_notifications import notification_blueprint - application.register_blueprint(notification_blueprint) + from app.v2.notifications.post_notifications import notification_blueprint as post_notifications + from app.v2.notifications.get_notifications import notification_blueprint as get_notifications + + application.register_blueprint(post_notifications) + application.register_blueprint(get_notifications) def init_app(app): diff --git a/app/models.py b/app/models.py index a1d7fa164..eaebdfc03 100644 --- a/app/models.py +++ b/app/models.py @@ -1,5 +1,6 @@ import uuid import datetime +from flask import url_for from sqlalchemy.dialects.postgresql import ( UUID, @@ -22,7 +23,8 @@ from app.authentication.utils import get_secret from app import ( db, encryption, - DATETIME_FORMAT) + DATETIME_FORMAT +) from app.history_meta import Versioned @@ -281,6 +283,10 @@ class Template(db.Model): created_by = db.relationship('User') version = db.Column(db.Integer, default=1, nullable=False) + def get_link(self): + # TODO: use "/v2/" route once available + return url_for("template.get_template_by_id_and_service_id", service_id=self.service_id, template_id=self.id) + class TemplateHistory(db.Model): __tablename__ = 'templates_history' @@ -553,6 +559,49 @@ class Notification(db.Model): return provider_rate.rate * self.billable_units + def completed_at(self): + if self.status in [ + NOTIFICATION_DELIVERED, + NOTIFICATION_FAILED, + NOTIFICATION_TECHNICAL_FAILURE, + NOTIFICATION_TEMPORARY_FAILURE, + NOTIFICATION_PERMANENT_FAILURE + ]: + return self.updated_at.strftime(DATETIME_FORMAT) + + return None + + def serialize(self): + + template_dict = { + 'version': self.template.version, + 'id': self.template.id, + 'uri': self.template.get_link() + } + + serialized = { + "id": self.id, + "reference": self.client_reference, + "email_address": self.to if self.notification_type == EMAIL_TYPE else None, + "phone_number": self.to if self.notification_type == SMS_TYPE else None, + "line_1": None, + "line_2": None, + "line_3": None, + "line_4": None, + "line_5": None, + "line_6": None, + "postcode": None, + "cost": self.cost(), + "type": self.notification_type, + "status": self.status, + "template": template_dict, + "created_at": self.created_at.strftime(DATETIME_FORMAT), + "sent_at": self.sent_at.strftime(DATETIME_FORMAT) if self.sent_at else None, + "completed_at": self.completed_at() + } + + return serialized + class NotificationHistory(db.Model): __tablename__ = 'notification_history' diff --git a/app/v2/notifications/get_notifications.py b/app/v2/notifications/get_notifications.py index b2fee08e0..405713dd4 100644 --- a/app/v2/notifications/get_notifications.py +++ b/app/v2/notifications/get_notifications.py @@ -1,9 +1,17 @@ +from flask import jsonify + +from app import api_user +from app.dao import notifications_dao from app.v2.notifications import notification_blueprint @notification_blueprint.route("/", methods=['GET']) def get_notification_by_id(id): - pass + notification = notifications_dao.get_notification_with_personalisation( + str(api_user.service_id), id, key_type=None + ) + + return jsonify(notification.serialize()), 200 @notification_blueprint.route("/", methods=['GET']) diff --git a/tests/app/v2/notifications/test_get_notifications.py b/tests/app/v2/notifications/test_get_notifications.py new file mode 100644 index 000000000..a9c583b5b --- /dev/null +++ b/tests/app/v2/notifications/test_get_notifications.py @@ -0,0 +1,46 @@ +import json + +from app import DATETIME_FORMAT +from tests import create_authorization_header + + +def test_get_notification_by_id_returns_200(client, sample_notification): + auth_header = create_authorization_header(service_id=sample_notification.service_id) + + response = client.get( + path='/v2/notifications/{}'.format(sample_notification.id), + headers=[('Content-Type', 'application/json'), auth_header]) + + assert response.status_code == 200 + assert response.headers['Content-type'] == 'application/json' + + json_response = json.loads(response.get_data(as_text=True)) + + expected_template_response = { + 'id': '{}'.format(sample_notification.serialize()['template']['id']), + 'version': sample_notification.serialize()['template']['version'], + 'uri': sample_notification.serialize()['template']['uri'] + } + + expected_response = { + 'id': '{}'.format(sample_notification.id), + 'reference': None, + 'email_address': None, + 'phone_number': '{}'.format(sample_notification.to), + 'line_1': None, + 'line_2': None, + 'line_3': None, + 'line_4': None, + 'line_5': None, + 'line_6': None, + 'postcode': None, + 'cost': sample_notification.cost(), + 'type': '{}'.format(sample_notification.notification_type), + 'status': '{}'.format(sample_notification.status), + 'template': expected_template_response, + 'created_at': sample_notification.created_at.strftime(DATETIME_FORMAT), + 'sent_at': sample_notification.sent_at, + 'completed_at': sample_notification.completed_at() + } + + assert json_response == expected_response diff --git a/tests/app/v2/notifications/test_notification_schemas.py b/tests/app/v2/notifications/test_notification_schemas.py index 5597ad377..73afbb29e 100644 --- a/tests/app/v2/notifications/test_notification_schemas.py +++ b/tests/app/v2/notifications/test_notification_schemas.py @@ -4,8 +4,9 @@ import pytest from flask import json from jsonschema import ValidationError -from app.v2.notifications.notification_schemas import post_sms_request, post_sms_response, post_email_request, \ - post_email_response +from app.v2.notifications.notification_schemas import ( + post_sms_request, post_sms_response, post_email_request, post_email_response +) from app.schema_validation import validate valid_json = {"phone_number": "07515111111",