diff --git a/app/__init__.py b/app/__init__.py index af3f15c74..e0928a4b9 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -66,7 +66,6 @@ def create_app(app_name=None): from app.notifications.rest import notifications as notifications_blueprint from app.invite.rest import invite as invite_blueprint from app.accept_invite.rest import accept_invite - from app.notifications_statistics.rest import notifications_statistics as notifications_statistics_blueprint from app.template_statistics.rest import template_statistics as template_statistics_blueprint from app.events.rest import events as events_blueprint from app.provider_details.rest import provider_details as provider_details_blueprint @@ -81,7 +80,7 @@ def create_app(app_name=None): application.register_blueprint(job_blueprint) application.register_blueprint(invite_blueprint) application.register_blueprint(accept_invite, url_prefix='/invite') - application.register_blueprint(notifications_statistics_blueprint) + application.register_blueprint(template_statistics_blueprint) application.register_blueprint(events_blueprint) application.register_blueprint(provider_details_blueprint, url_prefix='/provider-details') diff --git a/app/dao/notifications_dao.py b/app/dao/notifications_dao.py index ed900bdbb..597ab5968 100644 --- a/app/dao/notifications_dao.py +++ b/app/dao/notifications_dao.py @@ -7,9 +7,8 @@ from datetime import ( from flask import current_app from werkzeug.datastructures import MultiDict -from sqlalchemy import (desc, func, Integer, or_, and_, asc) +from sqlalchemy import (desc, func, or_, and_, asc) from sqlalchemy.orm import joinedload -from sqlalchemy.sql.expression import cast from app import db from app.dao import days_ago @@ -34,29 +33,14 @@ from app.dao.dao_utils import transactional from app.statsd_decorators import statsd -@statsd(namespace="dao") -def dao_get_notification_statistics_for_service(service_id, limit_days=None): - query_filter = [NotificationStatistics.service_id == service_id] - if limit_days is not None: - query_filter.append(NotificationStatistics.day >= days_ago(limit_days)) - return NotificationStatistics.query.filter(*query_filter)\ - .order_by(desc(NotificationStatistics.day))\ - .all() - - -@statsd(namespace="dao") def dao_get_notification_statistics_for_service_and_day(service_id, day): + # only used by stat-updating code in tasks.py return NotificationStatistics.query.filter_by( service_id=service_id, day=day ).order_by(desc(NotificationStatistics.day)).first() -@statsd(namespace="dao") -def dao_get_notification_statistics_for_day(day): - return NotificationStatistics.query.filter_by(day=day).all() - - @statsd(namespace="dao") def dao_get_potential_notification_statistics_for_day(day): all_services = db.session.query( @@ -105,34 +89,6 @@ def create_notification_statistics_dict(service_id, day): } -@statsd(namespace="dao") -def dao_get_7_day_agg_notification_statistics_for_service(service_id, - date_from, - week_count=52): - doy = date_from.timetuple().tm_yday - return db.session.query( - cast(func.floor((func.extract('doy', NotificationStatistics.day) - doy) / 7), Integer), - cast(func.sum(NotificationStatistics.emails_requested), Integer), - cast(func.sum(NotificationStatistics.emails_delivered), Integer), - cast(func.sum(NotificationStatistics.emails_failed), Integer), - cast(func.sum(NotificationStatistics.sms_requested), Integer), - cast(func.sum(NotificationStatistics.sms_delivered), Integer), - cast(func.sum(NotificationStatistics.sms_failed), Integer) - ).filter( - NotificationStatistics.service_id == service_id - ).filter( - NotificationStatistics.day >= date_from - ).filter( - NotificationStatistics.day < date_from + timedelta(days=7 * week_count) - ).group_by( - func.floor(((func.extract('doy', NotificationStatistics.day) - doy) / 7)) - ).order_by( - desc(func.floor(((func.extract('doy', NotificationStatistics.day) - doy) / 7))) - ).limit( - week_count - ) - - @statsd(namespace="dao") def dao_get_template_usage(service_id, limit_days=None): table = NotificationHistory diff --git a/app/notifications_statistics/__init__.py b/app/notifications_statistics/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/notifications_statistics/rest.py b/app/notifications_statistics/rest.py deleted file mode 100644 index 6613b10f8..000000000 --- a/app/notifications_statistics/rest.py +++ /dev/null @@ -1,105 +0,0 @@ -from datetime import ( - date, - timedelta, - datetime -) - -from flask import ( - Blueprint, - jsonify, - request, - current_app -) - -from app import DATE_FORMAT - -from app.dao.notifications_dao import ( - dao_get_notification_statistics_for_service, - dao_get_7_day_agg_notification_statistics_for_service, - dao_get_notification_statistics_for_service_and_day -) -from app.schemas import ( - notifications_statistics_schema, - week_aggregate_notification_statistics_schema -) - -notifications_statistics = Blueprint( - 'notifications-statistics', - __name__, url_prefix='/service//notifications-statistics' -) - -from app.errors import ( - register_errors, - InvalidRequest -) - -register_errors(notifications_statistics) - - -@notifications_statistics.route('', methods=['GET']) -def get_all_notification_statistics_for_service(service_id): - - if request.args.get('limit_days'): - try: - statistics = dao_get_notification_statistics_for_service( - service_id=service_id, - limit_days=int(request.args['limit_days']) - ) - except ValueError as e: - message = '{} is not an integer'.format(request.args['limit_days']) - errors = {'limit_days': [message]} - raise InvalidRequest(errors, status_code=400) - else: - statistics = dao_get_notification_statistics_for_service(service_id=service_id) - - data, errors = notifications_statistics_schema.dump(statistics, many=True) - return jsonify(data=data) - - -@notifications_statistics.route('/day/', methods=['GET']) -def get_notification_statistics_for_service_for_day(service_id, day): - - try: - datetime.strptime(day, DATE_FORMAT) - except ValueError: - raise InvalidRequest('Invalid date {}'.format(day), status_code=400) - - service_stats = dao_get_notification_statistics_for_service_and_day( - service_id, - day - ) - - if not service_stats: - message = 'No statistics found for service id: {} on day: {} '.format(service_id, day) - errors = {'not found': [message]} - raise InvalidRequest(errors, status_code=404) - - data = notifications_statistics_schema.dump(service_stats).data - return jsonify(data=data) - - -@notifications_statistics.route('/seven_day_aggregate') -def get_notification_statistics_for_service_seven_day_aggregate(service_id): - data = week_aggregate_notification_statistics_schema.load(request.args).data - date_from = data['date_from'] if 'date_from' in data else date(date.today().year, 4, 1) - week_count = data['week_count'] if 'week_count' in data else 52 - stats = dao_get_7_day_agg_notification_statistics_for_service( - service_id, - date_from, - week_count).all() - json_stats = [] - for x in range(week_count - 1, -1, -1): - week_stats = stats.pop(0) if len(stats) > 0 and stats[0][0] == x else [x, 0, 0, 0, 0, 0, 0] - week_start = (date_from + timedelta(days=week_stats[0] * 7)) - if week_start <= date.today(): - json_stats.append({ - 'week_start': week_start.strftime('%Y-%m-%d'), - 'week_end': (date_from + timedelta(days=(week_stats[0] * 7) + 6)).strftime('%Y-%m-%d'), - 'emails_requested': week_stats[1], - 'emails_delivered': week_stats[2], - 'emails_failed': week_stats[3], - 'sms_requested': week_stats[4], - 'sms_delivered': week_stats[5], - 'sms_failed': week_stats[6] - }) - return jsonify(data=json_stats) diff --git a/app/schemas.py b/app/schemas.py index a28c4aa94..7928b8c29 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -469,30 +469,6 @@ class OrganisationSchema(BaseSchema): strict = True -class FromToDateSchema(ma.Schema): - - class Meta: - strict = True - - date_from = fields.Date() - date_to = fields.Date() - - @validates('date_from') - def validate_date_from(self, value): - _validate_not_in_future(value) - - @validates('date_to') - def validate_date_to(self, value): - _validate_not_in_future(value) - - @validates_schema - def validate_dates(self, data): - df = data.get('date_from') - dt = data.get('date_to') - if (df and dt) and (df > dt): - raise ValidationError("date_from needs to be greater than date_to") - - class DaySchema(ma.Schema): class Meta: @@ -505,23 +481,6 @@ class DaySchema(ma.Schema): _validate_not_in_future(value) -class WeekAggregateNotificationStatisticsSchema(ma.Schema): - - class Meta: - strict = True - - date_from = fields.Date() - week_count = fields.Int() - - @validates('date_from') - def validate_date_from(self, value): - _validate_not_in_future(value) - - @validates('week_count') - def validate_week_count(self, value): - _validate_positive_number(value) - - class UnarchivedTemplateSchema(BaseSchema): archived = fields.Boolean(required=True) @@ -562,8 +521,6 @@ api_key_history_schema = ApiKeyHistorySchema() template_history_schema = TemplateHistorySchema() event_schema = EventSchema() organisation_schema = OrganisationSchema() -from_to_date_schema = FromToDateSchema() provider_details_schema = ProviderDetailsSchema() -week_aggregate_notification_statistics_schema = WeekAggregateNotificationStatisticsSchema() day_schema = DaySchema() unarchived_template_schema = UnarchivedTemplateSchema() diff --git a/app/service/rest.py b/app/service/rest.py index 6f45b6da8..1c0096000 100644 --- a/app/service/rest.py +++ b/app/service/rest.py @@ -1,5 +1,3 @@ -from datetime import date, timedelta - from flask import ( jsonify, request, @@ -32,7 +30,6 @@ from app.schemas import ( service_schema, api_key_schema, user_schema, - from_to_date_schema, permission_schema, notification_with_template_schema, notifications_filter_schema, diff --git a/tests/app/dao/test_notification_dao.py b/tests/app/dao/test_notification_dao.py index 9f2c9a90c..933746c48 100644 --- a/tests/app/dao/test_notification_dao.py +++ b/tests/app/dao/test_notification_dao.py @@ -21,19 +21,21 @@ from app.models import ( from app.dao.notifications_dao import ( dao_create_notification, - dao_update_notification, - get_notification_with_personalisation, - get_notification_for_job, - get_notifications_for_job, - dao_get_notification_statistics_for_service, - delete_notifications_created_more_than_a_week_ago, + dao_get_last_template_usage, dao_get_notification_statistics_for_service_and_day, + dao_get_potential_notification_statistics_for_day, + dao_get_template_usage, + dao_update_notification, + delete_notifications_created_more_than_a_week_ago, + get_notification_by_id, + get_notification_for_job, + get_notification_with_personalisation, + get_notifications_for_job, + get_notifications_for_service, update_notification_status_by_id, - update_provider_stats, update_notification_status_by_reference, - get_notifications_for_service, dao_get_7_day_agg_notification_statistics_for_service, - dao_get_potential_notification_statistics_for_day, dao_get_notification_statistics_for_day, - get_notification_by_id, dao_get_template_usage, dao_get_last_template_usage) + update_provider_stats, +) from notifications_utils.template import get_sms_fragment_count @@ -41,13 +43,9 @@ from tests.app.conftest import (sample_notification, sample_template, sample_ema def test_should_have_decorated_notifications_dao_functions(): - assert dao_get_notification_statistics_for_service.__wrapped__.__name__ == 'dao_get_notification_statistics_for_service' # noqa assert dao_get_last_template_usage.__wrapped__.__name__ == 'dao_get_last_template_usage' # noqa assert dao_get_template_usage.__wrapped__.__name__ == 'dao_get_template_usage' # noqa - assert dao_get_notification_statistics_for_service_and_day.__wrapped__.__name__ == 'dao_get_notification_statistics_for_service_and_day' # noqa - assert dao_get_notification_statistics_for_day.__wrapped__.__name__ == 'dao_get_notification_statistics_for_day' # noqa assert dao_get_potential_notification_statistics_for_day.__wrapped__.__name__ == 'dao_get_potential_notification_statistics_for_day' # noqa - assert dao_get_7_day_agg_notification_statistics_for_service.__wrapped__.__name__ == 'dao_get_7_day_agg_notification_statistics_for_service' # noqa assert dao_create_notification.__wrapped__.__name__ == 'dao_create_notification' # noqa assert update_notification_status_by_id.__wrapped__.__name__ == 'update_notification_status_by_id' # noqa assert dao_update_notification.__wrapped__.__name__ == 'dao_update_notification' # noqa @@ -439,67 +437,6 @@ def test_should_be_able_to_get_all_statistics_for_a_service(sample_template, mmg _assert_notification_stats(sample_template.service.id, sms_requested=3) -def test_should_be_able_to_get_all_statistics_for_a_service_for_several_days(sample_template, mmg_provider): - data = _notification_json(sample_template) - - today = datetime.utcnow() - yesterday = datetime.utcnow() - timedelta(days=1) - two_days_ago = datetime.utcnow() - timedelta(days=2) - data.update({'created_at': today}) - notification_1 = Notification(**data) - data.update({'created_at': yesterday}) - notification_2 = Notification(**data) - data.update({'created_at': two_days_ago}) - notification_3 = Notification(**data) - - dao_create_notification(notification_1, sample_template.template_type) - dao_create_notification(notification_2, sample_template.template_type) - dao_create_notification(notification_3, sample_template.template_type) - - stats = dao_get_notification_statistics_for_service(sample_template.service.id) - assert len(stats) == 3 - assert stats[0].emails_requested == 0 - assert stats[0].sms_requested == 1 - assert stats[0].day == today.date() - assert stats[1].emails_requested == 0 - assert stats[1].sms_requested == 1 - assert stats[1].day == yesterday.date() - assert stats[2].emails_requested == 0 - assert stats[2].sms_requested == 1 - assert stats[2].day == two_days_ago.date() - - -def test_should_be_empty_list_if_no_statistics_for_a_service(sample_service): - assert len(dao_get_notification_statistics_for_service(sample_service.id)) == 0 - - -def test_should_be_able_to_get_all_statistics_for_a_service_for_several_days_previous(sample_template, - mmg_provider): - data = _notification_json(sample_template) - - today = datetime.utcnow() - seven_days_ago = datetime.utcnow() - timedelta(days=7) - eight_days_ago = datetime.utcnow() - timedelta(days=8) - data.update({'created_at': today}) - notification_1 = Notification(**data) - data.update({'created_at': seven_days_ago}) - notification_2 = Notification(**data) - data.update({'created_at': eight_days_ago}) - notification_3 = Notification(**data) - dao_create_notification(notification_1, sample_template.template_type) - dao_create_notification(notification_2, sample_template.template_type) - dao_create_notification(notification_3, sample_template.template_type) - - stats = dao_get_notification_statistics_for_service(sample_template.service.id, 7) - assert len(stats) == 2 - assert stats[0].emails_requested == 0 - assert stats[0].sms_requested == 1 - assert stats[0].day == today.date() - assert stats[1].emails_requested == 0 - assert stats[1].sms_requested == 1 - assert stats[1].day == seven_days_ago.date() - - def test_create_notification_creates_notification_with_personalisation(notify_db, notify_db_session, sample_template_with_placeholders, sample_job, mmg_provider): @@ -522,7 +459,7 @@ def test_create_notification_creates_notification_with_personalisation(notify_db assert data.template == notification_from_db.template assert data.template_version == notification_from_db.template_version assert data.created_at == notification_from_db.created_at - assert 'created' == notification_from_db.status + assert notification_from_db.status == 'created' assert {'name': 'Jo'} == notification_from_db.personalisation _assert_job_stats(sample_job.id, sent=1, count=1, delivered=0, failed=0) @@ -558,7 +495,7 @@ def test_save_notification_creates_sms_and_template_stats(sample_template, sampl assert data['template'] == notification_from_db.template assert data['template_version'] == notification_from_db.template_version assert data['created_at'] == notification_from_db.created_at - assert 'created' == notification_from_db.status + assert notification_from_db.status == 'created' _assert_job_stats(sample_job.id, sent=1, count=1, delivered=0, failed=0) stats = NotificationStatistics.query.filter(NotificationStatistics.service_id == sample_template.service.id).first() @@ -591,7 +528,7 @@ def test_save_notification_and_create_email_and_template_stats(sample_email_temp assert data['template'] == notification_from_db.template assert data['template_version'] == notification_from_db.template_version assert data['created_at'] == notification_from_db.created_at - assert 'created' == notification_from_db.status + assert notification_from_db.status == 'created' _assert_job_stats(sample_job.id, sent=1, count=1, delivered=0, failed=0) stats = NotificationStatistics.query.filter( @@ -728,7 +665,7 @@ def test_save_notification_and_increment_job(sample_template, sample_job, mmg_pr assert data['template'] == notification_from_db.template assert data['template_version'] == notification_from_db.template_version assert data['created_at'] == notification_from_db.created_at - assert 'created' == notification_from_db.status + assert notification_from_db.status == 'created' assert Job.query.get(sample_job.id).notifications_sent == 1 notification_2 = Notification(**data) @@ -779,7 +716,7 @@ def test_save_notification_and_increment_correct_job(notify_db, notify_db_sessio assert data['template'] == notification_from_db.template assert data['template_version'] == notification_from_db.template_version assert data['created_at'] == notification_from_db.created_at - assert 'created' == notification_from_db.status + assert notification_from_db.status == 'created' assert job_1.id != job_2.id _assert_job_stats(job_id=job_1.id, sent=1, count=1) _assert_job_stats(job_id=job_2.id, sent=0, count=1) @@ -800,7 +737,7 @@ def test_save_notification_with_no_job(sample_template, mmg_provider): assert data['template'] == notification_from_db.template assert data['template_version'] == notification_from_db.template_version assert data['created_at'] == notification_from_db.created_at - assert 'created' == notification_from_db.status + assert notification_from_db.status == 'created' def test_get_notification(sample_notification): @@ -826,7 +763,7 @@ def test_save_notification_no_job_id(sample_template, mmg_provider): assert data['service'] == notification_from_db.service assert data['template'] == notification_from_db.template assert data['template_version'] == notification_from_db.template_version - assert 'created' == notification_from_db.status + assert notification_from_db.status == 'created' assert data.get('job_id') is None diff --git a/tests/app/dao/test_notification_statistics_dao.py b/tests/app/dao/test_notification_statistics_dao.py deleted file mode 100644 index b8ffe8445..000000000 --- a/tests/app/dao/test_notification_statistics_dao.py +++ /dev/null @@ -1,122 +0,0 @@ -from datetime import (date, timedelta) - -from app.models import NotificationStatistics -from tests.app.conftest import sample_notification_statistics as create_sample_notification_statistics -from app.dao.notifications_dao import dao_get_7_day_agg_notification_statistics_for_service - - -def test_display_weekly_notification_statistics_sum_over_week(notify_db, - notify_db_session, - sample_service): - fools = date(2016, 4, 1) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=fools - ) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=fools + timedelta(days=1) - ) - assert dao_get_7_day_agg_notification_statistics_for_service( - sample_service.id, - fools - ).all() == [(0, 4, 2, 2, 4, 2, 2)] - - -def test_display_weekly_notification_statistics_separate_over_weeks(notify_db, - notify_db_session, - sample_service): - fools = date(2016, 4, 1) - next_week = fools + timedelta(days=7) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=fools - ) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=next_week - ) - assert dao_get_7_day_agg_notification_statistics_for_service( - sample_service.id, - fools - ).all() == [(1, 2, 1, 1, 2, 1, 1), (0, 2, 1, 1, 2, 1, 1)] - - -def test_display_weekly_notification_statistics_7_days_from_date_from(notify_db, - notify_db_session, - sample_service): - fools = date(2016, 4, 1) - eow_fools = fools + timedelta(days=6) - next_week = fools + timedelta(days=7) - two_weeks_later = fools + timedelta(days=14) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=fools - ) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=eow_fools - ) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=next_week - ) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=two_weeks_later - ) - assert dao_get_7_day_agg_notification_statistics_for_service( - sample_service.id, - fools - ).all() == [(2, 2, 1, 1, 2, 1, 1), (1, 2, 1, 1, 2, 1, 1), (0, 4, 2, 2, 4, 2, 2)] - - -def test_display_weekly_notification_statistics_week_number_misses_week(notify_db, - notify_db_session, - sample_service): - fools = date(2016, 4, 1) - two_weeks_later = fools + timedelta(days=14) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=fools - ) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=two_weeks_later - ) - assert dao_get_7_day_agg_notification_statistics_for_service( - sample_service.id, - fools - ).all() == [(2, 2, 1, 1, 2, 1, 1), (0, 2, 1, 1, 2, 1, 1)] - - -def test_display_weekly_notification_statistics_week_limit(notify_db, - notify_db_session, - sample_service): - fools = date(2016, 4, 1) - two_weeks_later = fools + timedelta(days=14) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=fools - ) - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=two_weeks_later - ) - assert dao_get_7_day_agg_notification_statistics_for_service( - sample_service.id, - fools, - 1 - ).all() == [(0, 2, 1, 1, 2, 1, 1)] diff --git a/tests/app/notifications/rest/test_callbacks.py b/tests/app/notifications/rest/test_callbacks.py index 738e8ae95..b6fc84757 100644 --- a/tests/app/notifications/rest/test_callbacks.py +++ b/tests/app/notifications/rest/test_callbacks.py @@ -4,9 +4,9 @@ from flask import json import app.celery.tasks from app.dao.notifications_dao import ( - get_notification_by_id, - dao_get_notification_statistics_for_service + get_notification_by_id ) +from app.models import NotificationStatistics from tests.app.conftest import sample_notification as create_sample_notification @@ -162,7 +162,7 @@ def test_firetext_callback_should_update_notification_status(notify_api, sample_ updated = get_notification_by_id(sample_notification.id) assert updated.status == 'delivered' assert get_notification_by_id(sample_notification.id).status == 'delivered' - stats = dao_get_notification_statistics_for_service(sample_notification.service_id)[0] + stats = get_notification_stats(sample_notification.service_id) assert stats.sms_delivered == 1 assert stats.sms_requested == 1 assert stats.sms_failed == 0 @@ -189,7 +189,7 @@ def test_firetext_callback_should_update_notification_status_failed(notify_api, sample_notification.id ) assert get_notification_by_id(sample_notification.id).status == 'permanent-failure' - stats = dao_get_notification_statistics_for_service(sample_notification.service_id)[0] + stats = get_notification_stats(sample_notification.service_id) assert stats.sms_delivered == 0 assert stats.sms_requested == 1 assert stats.sms_failed == 1 @@ -217,7 +217,7 @@ def test_firetext_callback_should_update_notification_status_pending(notify_api, notification.id ) assert get_notification_by_id(notification.id).status == 'pending' - stats = dao_get_notification_statistics_for_service(notification.service_id)[0] + stats = get_notification_stats(notification.service_id) assert stats.sms_delivered == 0 assert stats.sms_requested == 1 assert stats.sms_failed == 0 @@ -257,7 +257,7 @@ def test_firetext_callback_should_update_multiple_notification_status_sent( ), headers=[('Content-Type', 'application/x-www-form-urlencoded')]) - stats = dao_get_notification_statistics_for_service(notification1.service_id)[0] + stats = get_notification_stats(notification1.service_id) assert stats.sms_delivered == 3 assert stats.sms_requested == 3 assert stats.sms_failed == 0 @@ -481,7 +481,7 @@ def test_ses_callback_should_update_notification_status( assert json_resp['result'] == 'success' assert json_resp['message'] == 'SES callback succeeded' assert get_notification_by_id(notification.id).status == 'delivered' - stats = dao_get_notification_statistics_for_service(notification.service_id)[0] + stats = get_notification_stats(notification.service_id) assert stats.emails_delivered == 1 assert stats.emails_requested == 1 assert stats.emails_failed == 0 @@ -536,7 +536,7 @@ def test_ses_callback_should_update_multiple_notification_status_sent( assert resp2.status_code == 200 assert resp3.status_code == 200 - stats = dao_get_notification_statistics_for_service(notification1.service_id)[0] + stats = get_notification_stats(notification1.service_id) assert stats.emails_delivered == 3 assert stats.emails_requested == 3 assert stats.emails_failed == 0 @@ -568,7 +568,7 @@ def test_ses_callback_should_set_status_to_temporary_failure(notify_api, assert json_resp['result'] == 'success' assert json_resp['message'] == 'SES callback succeeded' assert get_notification_by_id(notification.id).status == 'temporary-failure' - stats = dao_get_notification_statistics_for_service(notification.service_id)[0] + stats = get_notification_stats(notification.service_id) assert stats.emails_delivered == 0 assert stats.emails_requested == 1 assert stats.emails_failed == 1 @@ -628,7 +628,7 @@ def test_ses_callback_should_set_status_to_permanent_failure(notify_api, assert json_resp['result'] == 'success' assert json_resp['message'] == 'SES callback succeeded' assert get_notification_by_id(notification.id).status == 'permanent-failure' - stats = dao_get_notification_statistics_for_service(notification.service_id)[0] + stats = get_notification_stats(notification.service_id) assert stats.emails_delivered == 0 assert stats.emails_requested == 1 assert stats.emails_failed == 1 @@ -730,3 +730,7 @@ def ses_hard_bounce_callback(): def ses_soft_bounce_callback(): return b'{\n "Type" : "Notification",\n "MessageId" : "ref",\n "TopicArn" : "arn:aws:sns:eu-west-1:123456789012:testing",\n "Message" : "{\\"notificationType\\":\\"Bounce\\",\\"bounce\\":{\\"bounceType\\":\\"Undetermined\\",\\"bounceSubType\\":\\"General\\"}, \\"mail\\":{\\"messageId\\":\\"ref\\",\\"timestamp\\":\\"2016-03-14T12:35:25.909Z\\",\\"source\\":\\"test@test-domain.com\\",\\"sourceArn\\":\\"arn:aws:ses:eu-west-1:123456789012:identity/testing-notify\\",\\"sendingAccountId\\":\\"123456789012\\",\\"destination\\":[\\"testing@digital.cabinet-office.gov.uk\\"]},\\"delivery\\":{\\"timestamp\\":\\"2016-03-14T12:35:26.567Z\\",\\"processingTimeMillis\\":658,\\"recipients\\":[\\"testing@digital.cabinet-office.gov.uk\\"],\\"smtpResponse\\":\\"250 2.0.0 OK 1457958926 uo5si26480932wjc.221 - gsmtp\\",\\"reportingMTA\\":\\"a6-238.smtp-out.eu-west-1.amazonses.com\\"}}",\n "Timestamp" : "2016-03-14T12:35:26.665Z",\n "SignatureVersion" : "1",\n "Signature" : "X8d7eTAOZ6wlnrdVVPYanrAlsX0SMPfOzhoTEBnQqYkrNWTqQY91C0f3bxtPdUhUtOowyPAOkTQ4KnZuzphfhVb2p1MyVYMxNKcBFB05/qaCX99+92fjw4x9LeUOwyGwMv5F0Vkfi5qZCcEw69uVrhYLVSTFTrzi/yCtru+yFULMQ6UhbY09GwiP6hjxZMVr8aROQy5lLHglqQzOuSZ4KeD85JjifHdKzlx8jjQ+uj+FLzHXPMAPmPU1JK9kpoHZ1oPshAFgPDpphJe+HwcJ8ezmk+3AEUr3wWli3xF+49y8Z2anASSVp6YI2YP95UT8Rlh3qT3T+V9V8rbSVislxA==",\n "SigningCertURL" : "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-bb750dd426d95ee9390147a5624348ee.pem",\n "UnsubscribeURL" : "https://sns.eu-west-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:eu-west-1:302763885840:preview-emails:d6aad3ef-83d6-4cf3-a470-54e2e75916da"\n}' # noqa + + +def get_notification_stats(service_id): + return NotificationStatistics.query.filter_by(service_id=service_id).one() diff --git a/tests/app/notifications/test_notification_statistics_rest.py b/tests/app/notifications/test_notification_statistics_rest.py deleted file mode 100644 index d298aa7c5..000000000 --- a/tests/app/notifications/test_notification_statistics_rest.py +++ /dev/null @@ -1,207 +0,0 @@ -import json -from datetime import ( - date, - timedelta -) - -from flask import url_for -from tests import create_authorization_header -from tests.app.conftest import sample_notification_statistics as create_sample_notification_statistics - -from freezegun import freeze_time - - -def test_get_notification_statistics_returns_empty_list_if_no_stats(notify_api, - notify_db, - notify_db_session, - sample_template, - sample_email_template): - with notify_api.test_request_context(): - with notify_api.test_client() as client: - - path = '/service/{}/notifications-statistics'.format(sample_email_template.service.id) - - auth_header = create_authorization_header( - service_id=sample_email_template.service_id) - - response = client.get(path, headers=[auth_header]) - assert response.status_code == 200 - - stats = json.loads(response.get_data(as_text=True)) - assert stats['data'] == [] - - -def test_get_week_aggregate_statistics(notify_api, - notify_db, - notify_db_session, - sample_service): - with notify_api.test_request_context(): - sample_notification_statistics = create_sample_notification_statistics( - notify_db, - notify_db_session, - day=date(date.today().year, 4, 1)) - with notify_api.test_client() as client: - endpoint = url_for( - 'notifications-statistics.get_notification_statistics_for_service_seven_day_aggregate', - service_id=sample_service.id) - auth_header = create_authorization_header( - service_id=sample_service.id) - - resp = client.get(endpoint, headers=[auth_header]) - assert resp.status_code == 200 - json_resp = json.loads(resp.get_data(as_text=True)) - week_len_index = len(json_resp['data']) - 1 - assert json_resp['data'][week_len_index]['emails_requested'] == 2 - assert json_resp['data'][week_len_index]['sms_requested'] == 2 - assert json_resp['data'][week_len_index]['week_start'] == date(date.today().year, 4, 1).strftime('%Y-%m-%d') - assert json_resp['data'][week_len_index]['week_end'] == date(date.today().year, 4, 7).strftime('%Y-%m-%d') - - -def test_get_week_aggregate_statistics_date_from(notify_api, - notify_db, - notify_db_session, - sample_service): - with notify_api.test_request_context(): - sample_notification_statistics = create_sample_notification_statistics( - notify_db, - notify_db_session, - day=date(date.today().year, 4, 1)) - date_from_str = date(date.today().year, 4, 1).strftime('%Y-%m-%d') - with notify_api.test_client() as client: - endpoint = url_for( - 'notifications-statistics.get_notification_statistics_for_service_seven_day_aggregate', - service_id=sample_service.id, - date_from=date_from_str) - auth_header = create_authorization_header( - service_id=sample_service.id) - - resp = client.get(endpoint, headers=[auth_header]) - assert resp.status_code == 200 - json_resp = json.loads(resp.get_data(as_text=True)) - week_len_index = len(json_resp['data']) - 1 - assert json_resp['data'][week_len_index]['emails_requested'] == 2 - assert json_resp['data'][week_len_index]['sms_requested'] == 2 - assert json_resp['data'][week_len_index]['week_start'] == date_from_str - assert json_resp['data'][week_len_index]['week_end'] == date(date.today().year, 4, 7).strftime('%Y-%m-%d') - - -def test_get_week_aggregate_statistics_date_in_future(notify_api, - notify_db, - notify_db_session, - sample_service): - with notify_api.test_request_context(): - with notify_api.test_client() as client: - endpoint = url_for( - 'notifications-statistics.get_notification_statistics_for_service_seven_day_aggregate', - service_id=sample_service.id, - date_from=(date.today() + timedelta(days=1)).strftime('%Y-%m-%d')) - auth_header = create_authorization_header( - service_id=sample_service.id) - - resp = client.get(endpoint, headers=[auth_header]) - assert resp.status_code == 400 - json_resp = json.loads(resp.get_data(as_text=True)) - assert json_resp['result'] == 'error' - assert json_resp['message']['date_from'][0] == 'Date cannot be in the future' - - -def test_get_week_aggregate_statistics_invalid_week_count(notify_api, - notify_db, - notify_db_session, - sample_service): - with notify_api.test_request_context(): - with notify_api.test_client() as client: - endpoint = url_for( - 'notifications-statistics.get_notification_statistics_for_service_seven_day_aggregate', - service_id=sample_service.id, - week_count=-1) - auth_header = create_authorization_header( - service_id=sample_service.id) - - resp = client.get(endpoint, headers=[auth_header]) - assert resp.status_code == 400 - json_resp = json.loads(resp.get_data(as_text=True)) - assert json_resp['result'] == 'error' - assert json_resp['message']['week_count'][0] == 'Not a positive integer' - - -@freeze_time('2016-01-01') -def test_get_notification_statistics_for_specific_day(notify_api, - notify_db, - notify_db_session, - sample_template): - the_day = date.today() - - sample_notification_statistics = create_sample_notification_statistics( - notify_db, - notify_db_session, - day=the_day) - - with notify_api.test_request_context(): - with notify_api.test_client() as client: - path = '/service/{}/notifications-statistics/day/{}'.format(sample_template.service_id, the_day) - auth_header = create_authorization_header(service_id=sample_template.service_id) - response = client.get(path, headers=[auth_header]) - assert response.status_code == 200 - stats = json.loads(response.get_data(as_text=True)) - - assert stats['data']['id'] == str(sample_notification_statistics.id) - assert stats['data']['day'] == the_day.strftime('%Y-%m-%d') - - another_day = the_day - timedelta(days=1) - path = '/service/{}/notifications-statistics/day/{}'.format(sample_template.service_id, another_day) - - response = client.get(path, headers=[auth_header]) - assert response.status_code == 404 - - -@freeze_time('2016-01-01') -def test_get_notification_statistics_for_specific_day_returns_404_if_no_stats(notify_api, - notify_db, - notify_db_session, - sample_template): - the_day = date.today() - - with notify_api.test_request_context(): - with notify_api.test_client() as client: - path = '/service/{}/notifications-statistics/day/{}'.format(sample_template.service_id, the_day) - auth_header = create_authorization_header(service_id=sample_template.service_id) - response = client.get(path, headers=[auth_header]) - assert response.status_code == 404 - - -@freeze_time('2016-01-01') -def test_get_notification_statistics_for_specific_day_returns_400_for_incorrect_date(notify_api, - notify_db, - notify_db_session, - sample_template): - the_day = date.today() - incorrect_date_format = the_day.strftime('%d-%m-%Y') - - create_sample_notification_statistics( - notify_db, - notify_db_session, - day=the_day) - - with notify_api.test_request_context(): - with notify_api.test_client() as client: - path = '/service/{}/notifications-statistics/day/{}'.format( - sample_template.service_id, - incorrect_date_format) - auth_header = create_authorization_header(service_id=sample_template.service_id) - response = client.get(path, headers=[auth_header]) - assert response.status_code == 400 - resp_json = json.loads(response.get_data(as_text=True)) - assert resp_json['result'] == 'error' - assert resp_json['message'] == 'Invalid date 01-01-2016' - - another_dodgy_date = 'fish' - path = '/service/{}/notifications-statistics/day/{}'.format( - sample_template.service_id, - another_dodgy_date) - - response = client.get(path, headers=[auth_header]) - assert response.status_code == 400 - resp_json = json.loads(response.get_data(as_text=True)) - assert resp_json['result'] == 'error' - assert resp_json['message'] == 'Invalid date fish'