From 6a5e9472203b44ff8e1aa54a5a5be53cc4c11cb6 Mon Sep 17 00:00:00 2001 From: Chris Hill-Scott Date: Fri, 30 Sep 2016 17:17:28 +0100 Subject: [PATCH] Add DAO for getting billable units/financial year MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to invoice people we need to know how many text message fragments they’ve sent per month. This should be per (government) financial year, ie April 1st to April 1st because we’ll only ever show a page for one year (because the 250,000 allowance is topped up at the start of every financial year). This commit only does the DAO bit, not the REST bit. --- app/dao/notifications_dao.py | 27 ++++++++++++++- tests/app/dao/test_notification_dao.py | 46 +++++++++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/app/dao/notifications_dao.py b/app/dao/notifications_dao.py index c289f60ed..3985f3ea0 100644 --- a/app/dao/notifications_dao.py +++ b/app/dao/notifications_dao.py @@ -7,7 +7,7 @@ from datetime import ( from flask import current_app from werkzeug.datastructures import MultiDict -from sqlalchemy import (desc, func, or_, and_, asc) +from sqlalchemy import (desc, func, or_, and_, asc, cast, Text) from sqlalchemy.orm import joinedload from app import db @@ -209,6 +209,24 @@ def get_notifications_for_job(service_id, job_id, filter_dict=None, page=1, page ) +@statsd(namespace="dao") +def get_notification_billable_unit_count_per_month(service_id, year): + start, end = get_financial_year(year) + return db.session.query( + func.to_char(NotificationHistory.created_at, "FMMonth"), + func.sum(NotificationHistory.billable_units) + ).group_by( + func.to_char(NotificationHistory.created_at, "FMMonth"), + func.to_char(NotificationHistory.created_at, "YYYY-MM") + ).order_by( + func.to_char(NotificationHistory.created_at, "YYYY-MM") + ).filter( + NotificationHistory.service_id == service_id, + NotificationHistory.created_at >= start, + NotificationHistory.created_at < end + ).all() + + @statsd(namespace="dao") def get_notification_with_personalisation(service_id, notification_id, key_type): filter_dict = {'service_id': service_id, 'id': notification_id} @@ -319,3 +337,10 @@ def dao_timeout_notifications(timeout_period_in_seconds): update({'status': NOTIFICATION_TEMPORARY_FAILURE, 'updated_at': update_at}, synchronize_session=False) db.session.commit() return updated + + +def get_financial_year(year): + return ( + date(year, 4, 1), + date(year + 1, 4, 1) + ) diff --git a/tests/app/dao/test_notification_dao.py b/tests/app/dao/test_notification_dao.py index 97885f50a..7e7ac65d8 100644 --- a/tests/app/dao/test_notification_dao.py +++ b/tests/app/dao/test_notification_dao.py @@ -31,13 +31,15 @@ from app.dao.notifications_dao import ( delete_notifications_created_more_than_a_week_ago, get_notification_by_id, get_notification_for_job, + get_notification_billable_unit_count_per_month, get_notification_with_personalisation, get_notifications_for_job, get_notifications_for_service, update_notification_status_by_id, update_notification_status_by_reference, dao_delete_notifications_and_history_by_id, - dao_timeout_notifications) + dao_timeout_notifications, + get_financial_year) from notifications_utils.template import get_sms_fragment_count @@ -685,6 +687,42 @@ def test_get_all_notifications_for_job_by_status(notify_db, notify_db_session, s assert len(notifications(filter_dict={'status': NOTIFICATION_STATUS_TYPES[:3]}).items) == 3 +def test_get_notification_billable_unit_count_per_month(notify_db, notify_db_session, sample_service): + + for year, month, day in ( + (2017, 1, 1), + (2016, 8, 1), + (2016, 7, 31), + (2016, 4, 6), + (2016, 4, 6), + (2016, 4, 1), + (2016, 3, 31), + (2016, 1, 1) + ): + sample_notification( + notify_db, notify_db_session, service=sample_service, + created_at=date(year, month, day) + ) + + for financial_year, months in ( + ( + 2017, + [] + ), + ( + 2016, + [('April', 3), ('July', 1), ('August', 1), ('January', 1)] + ), + ( + 2015, + [('January', 1), ('March', 1)] + ) + ): + assert get_notification_billable_unit_count_per_month( + sample_service.id, financial_year + ) == months + + def test_update_notification(sample_notification, sample_template): assert sample_notification.status == 'created' sample_notification.status = 'failed' @@ -1158,3 +1196,9 @@ def test_should_exclude_test_key_notifications_by_default( all_notifications = get_notifications_for_service(sample_service.id, limit_days=1, key_type=KEY_TYPE_TEST).items assert len(all_notifications) == 1 + + +def test_get_financial_year(): + start, end = get_financial_year(2000) + assert start == date(2000, 4, 1) + assert end == date(2001, 4, 1)