From b6cc5b00ba08bebca2f979138f4c9c5133119345 Mon Sep 17 00:00:00 2001 From: Imdad Ahad Date: Fri, 27 Jan 2017 12:22:36 +0000 Subject: [PATCH] Add dao method to get sms and email notification counts for a date range and previous day --- app/dao/notifications_dao.py | 40 ++++- tests/app/conftest.py | 21 ++- tests/app/dao/test_notification_dao.py | 195 ++++++++++++++++++++++++- 3 files changed, 245 insertions(+), 11 deletions(-) diff --git a/app/dao/notifications_dao.py b/app/dao/notifications_dao.py index 8ab6b0dd0..cac613243 100644 --- a/app/dao/notifications_dao.py +++ b/app/dao/notifications_dao.py @@ -1,4 +1,3 @@ - import pytz from datetime import ( datetime, @@ -23,10 +22,16 @@ from app.models import ( NOTIFICATION_PENDING, NOTIFICATION_TECHNICAL_FAILURE, NOTIFICATION_TEMPORARY_FAILURE, - KEY_TYPE_NORMAL, KEY_TYPE_TEST) + NOTIFICATION_STATUS_TYPES_COMPLETED, + KEY_TYPE_NORMAL, KEY_TYPE_TEST +) from app.dao.dao_utils import transactional from app.statsd_decorators import statsd +from app.utils import ( + get_midnight_for_date, + get_midnight_for_day_before +) def dao_get_notification_statistics_for_service_and_day(service_id, day): @@ -408,3 +413,34 @@ def get_april_fools(year): """ return pytz.timezone('Europe/London').localize(datetime(year, 4, 1, 0, 0, 0)).astimezone(pytz.UTC).replace( tzinfo=None) + + +def get_total_sent_notifications_in_date_range(start_date, end_date, notification_type): + result = db.session.query( + func.count(NotificationHistory.id).label('count') + ).filter( + NotificationHistory.key_type != KEY_TYPE_TEST, + NotificationHistory.status.in_(NOTIFICATION_STATUS_TYPES_COMPLETED), + NotificationHistory.created_at >= start_date, + NotificationHistory.created_at <= end_date, + NotificationHistory.notification_type == notification_type + ).first() + + return 0 if result is None else result.count + + +def get_total_sent_notifications_yesterday(): + today = datetime.utcnow() + start_date = get_midnight_for_day_before(today) + end_date = get_midnight_for_date(today) + + return { + "start_date": start_date, + "end_date": end_date, + "email": { + "count": get_total_sent_notifications_in_date_range(start_date, end_date, 'email') + }, + "sms": { + "count": get_total_sent_notifications_in_date_range(start_date, end_date, 'sms') + } + } diff --git a/tests/app/conftest.py b/tests/app/conftest.py index 559537744..49afa591f 100644 --- a/tests/app/conftest.py +++ b/tests/app/conftest.py @@ -526,14 +526,21 @@ def mock_statsd_timing(mocker): @pytest.fixture(scope='function') -def sample_notification_history(notify_db, - notify_db_session, - sample_template, - status='created', - created_at=None): +def sample_notification_history( + notify_db, + notify_db_session, + sample_template, + status='created', + created_at=None, + notification_type=None, + key_type=KEY_TYPE_NORMAL +): if created_at is None: created_at = datetime.utcnow() + if notification_type is None: + notification_type = sample_template.template_type + notification_history = NotificationHistory( id=uuid.uuid4(), service=sample_template.service, @@ -541,8 +548,8 @@ def sample_notification_history(notify_db, template_version=sample_template.version, status=status, created_at=created_at, - notification_type=sample_template.template_type, - key_type=KEY_TYPE_NORMAL + notification_type=notification_type, + key_type=key_type ) notify_db.session.add(notification_history) notify_db.session.commit() diff --git a/tests/app/dao/test_notification_dao.py b/tests/app/dao/test_notification_dao.py index a6b75196f..14865ca1c 100644 --- a/tests/app/dao/test_notification_dao.py +++ b/tests/app/dao/test_notification_dao.py @@ -35,6 +35,8 @@ from app.dao.notifications_dao import ( get_notification_with_personalisation, get_notifications_for_job, get_notifications_for_service, + get_total_sent_notifications_in_date_range, + get_total_sent_notifications_yesterday, update_notification_status_by_id, update_notification_status_by_reference, dao_delete_notifications_and_history_by_id, @@ -44,8 +46,20 @@ from app.dao.notifications_dao import ( from app.dao.services_dao import dao_update_service -from tests.app.conftest import (sample_notification, sample_template, sample_email_template, sample_service, sample_job, - sample_api_key) +from app.utils import ( + get_midnight_for_date, + get_midnight_for_day_before +) + +from tests.app.conftest import ( + sample_notification, + sample_template, + sample_email_template, + sample_service, + sample_job, + sample_api_key, + sample_notification_history as create_notification_history +) def test_should_have_decorated_notifications_dao_functions(): @@ -1306,3 +1320,180 @@ def test_get_april_fools(): april_fools = get_april_fools(2016) assert str(april_fools) == '2016-03-31 23:00:00' assert april_fools.tzinfo is None + + +@pytest.mark.parametrize('notification_type', ['sms', 'email']) +def test_get_total_sent_notifications_in_date_range_returns_only_in_date_range( + notify_db, + notify_db_session, + sample_template, + notification_type +): + notification_history = partial( + create_notification_history, + notify_db, + notify_db_session, + sample_template, + notification_type=notification_type, + status='delivered' + ) + + start_date = datetime(2000, 3, 30, 0, 0, 0, 0) + with freeze_time(start_date): + notification_history(created_at=start_date + timedelta(hours=3)) + notification_history(created_at=start_date + timedelta(hours=5, minutes=10)) + notification_history(created_at=start_date + timedelta(hours=11, minutes=59)) + + end_date = datetime(2000, 3, 31, 0, 0, 0, 0) + notification_history(created_at=end_date + timedelta(seconds=1)) + notification_history(created_at=end_date + timedelta(minutes=10)) + + total_count = get_total_sent_notifications_in_date_range(start_date, end_date, notification_type) + assert total_count == 3 + + +@pytest.mark.parametrize('notification_type', ['sms', 'email']) +def test_get_total_sent_notifications_in_date_range_excludes_created_and_sending( + notify_db, + notify_db_session, + sample_template, + notification_type +): + notification_history = partial( + create_notification_history, + notify_db, + notify_db_session, + sample_template, + notification_type=notification_type + ) + + start_date = datetime(2000, 3, 30, 0, 0, 0, 0) + end_date = datetime(2000, 3, 31, 0, 0, 0, 0) + with freeze_time(start_date): + notification_history(status='sending') + notification_history(status='created') + notification_history(status='failed') + notification_history(status='delivered') + + total_count = get_total_sent_notifications_in_date_range(start_date, end_date, notification_type) + assert total_count == 2 + + +@pytest.mark.parametrize('notification_type', ['sms', 'email']) +def test_get_total_sent_notifications_in_date_range_excludes_test_key_notifications( + notify_db, + notify_db_session, + sample_template, + notification_type +): + notification_history = partial( + create_notification_history, + notify_db, + notify_db_session, + sample_template, + notification_type=notification_type, + status='delivered' + ) + + start_date = datetime(2000, 3, 30, 0, 0, 0, 0) + end_date = datetime(2000, 3, 31, 0, 0, 0, 0) + with freeze_time(start_date): + notification_history(key_type=KEY_TYPE_TEAM) + notification_history(key_type=KEY_TYPE_TEAM) + notification_history(key_type=KEY_TYPE_NORMAL) + notification_history(key_type=KEY_TYPE_TEST) + + total_count = get_total_sent_notifications_in_date_range(start_date, end_date, notification_type) + assert total_count == 3 + + +def test_get_total_sent_notifications_for_sms_excludes_email_counts( + notify_db, + notify_db_session, + sample_template +): + notification_history = partial( + create_notification_history, + notify_db, + notify_db_session, + sample_template, + status='delivered' + ) + + start_date = datetime(2000, 3, 30, 0, 0, 0, 0) + end_date = datetime(2000, 3, 31, 0, 0, 0, 0) + with freeze_time(start_date): + notification_history(notification_type='email') + notification_history(notification_type='email') + notification_history(notification_type='sms') + notification_history(notification_type='sms') + notification_history(notification_type='sms') + + total_count = get_total_sent_notifications_in_date_range(start_date, end_date, 'sms') + assert total_count == 3 + + +def test_get_total_sent_notifications_for_sms_excludes_sms_counts( + notify_db, + notify_db_session, + sample_template +): + notification_history = partial( + create_notification_history, + notify_db, + notify_db_session, + sample_template, + status='delivered' + ) + + start_date = datetime(2000, 3, 30, 0, 0, 0, 0) + end_date = datetime(2000, 3, 31, 0, 0, 0, 0) + with freeze_time(start_date): + notification_history(notification_type='email') + notification_history(notification_type='email') + notification_history(notification_type='sms') + notification_history(notification_type='sms') + notification_history(notification_type='sms') + + total_count = get_total_sent_notifications_in_date_range(start_date, end_date, 'email') + assert total_count == 2 + + +@freeze_time("2016-01-11 12:30:00") +def test_get_total_sent_notifications_yesterday_returns_expected_totals_dict( + notify_db, + notify_db_session, + sample_template +): + notification_history = partial( + create_notification_history, + notify_db, + notify_db_session, + sample_template, + status='delivered' + ) + + notification_history(notification_type='email') + notification_history(notification_type='sms') + + # Create some notifications for the day before + yesterday = datetime(2016, 1, 10, 15, 30, 0, 0) + with freeze_time(yesterday): + notification_history(notification_type='sms') + notification_history(notification_type='sms') + notification_history(notification_type='email') + notification_history(notification_type='email') + notification_history(notification_type='email') + + total_count_dict = get_total_sent_notifications_yesterday() + + assert total_count_dict == { + "start_date": get_midnight_for_day_before(datetime.utcnow()), + "end_date": get_midnight_for_date(datetime.utcnow()), + "email": { + "count": 3 + }, + "sms": { + "count": 2 + } + }