diff --git a/app/dao/date_util.py b/app/dao/date_util.py index cac09dee2..d93986b45 100644 --- a/app/dao/date_util.py +++ b/app/dao/date_util.py @@ -92,4 +92,4 @@ def generate_date_range(start_date, end_date=None, days=0): pass current_date += timedelta(days=1) else: - return "A start_date or number of days must be specified" + return "An end_date or number of days must be specified" diff --git a/app/dao/services_dao.py b/app/dao/services_dao.py index 74f8094a8..a7c41a28e 100644 --- a/app/dao/services_dao.py +++ b/app/dao/services_dao.py @@ -1,3 +1,4 @@ +from re import I import uuid from datetime import timedelta @@ -8,7 +9,7 @@ from sqlalchemy.sql.expression import and_, asc, case, func from app import db from app.dao.dao_utils import VersionOptions, autocommit, version_class -from app.dao.date_util import get_current_calendar_year +from app.dao.date_util import generate_date_range, get_current_calendar_year from app.dao.organization_dao import dao_get_organization_by_email_address from app.dao.service_sms_sender_dao import insert_service_sms_sender from app.dao.service_user_dao import dao_get_service_user @@ -41,6 +42,7 @@ from app.models import ( User, VerifyCode, ) +from app.service import statistics from app.utils import ( escape_special_characters, get_archived_db_column_value, @@ -689,3 +691,28 @@ def fetch_notification_stats_for_service_by_month_by_user( ) .all() ) + + +def get_specific_days_stats(results, start_date, days=None, end_date=None): + if days is not None and end_date is not None: + raise ValueError("Only set days OR set end_date, not both.") + elif days is not None: + gen_range = generate_date_range(start_date, days=days) + elif end_date is not None: + gen_range = generate_date_range(start_date, end_date) + else: + raise ValueError("Either days or end_date must be set.") + + grouped_results = { + date: [] for date in gen_range + } | { + day.date(): [notification_type, status, day, count] + for notification_type, status, day, count in results + } + + stats = { + day.strftime("%Y-%m-%d"): statistics.format_statistics(rows) + for day, rows in grouped_results.items() + } + + return stats diff --git a/app/service/rest.py b/app/service/rest.py index ea59387d8..516a22c3e 100644 --- a/app/service/rest.py +++ b/app/service/rest.py @@ -78,6 +78,7 @@ from app.dao.services_dao import ( dao_update_service, fetch_notification_stats_for_service_by_month_by_user, get_services_by_partial_name, + get_specific_days_stats, ) from app.dao.templates_dao import dao_get_template_by_id from app.dao.users_dao import get_user_by_id @@ -234,18 +235,7 @@ def get_service_statistics_for_specific_days(service_id, start, days=1): results = dao_fetch_stats_for_service_from_days(service_id, start_date, end_date) - grouped_results = defaultdict(list) - for row in results: - notification_type, status, day, count = row - grouped_results[day.date()].append(row) - - for date in generate_date_range(start_date, days=days): - if date not in grouped_results: - grouped_results[date] = [] - - stats = {} - for day, rows in grouped_results.items(): - stats[day.strftime("%Y-%m-%d")] = statistics.format_statistics(rows) + stats = get_specific_days_stats(results, start_date, days=days) return stats @@ -276,20 +266,7 @@ def get_service_statistics_for_specific_days_by_user( service_id, start_date, end_date, user_id ) - grouped_results = defaultdict(list) - for row in results: - notification_type, status, day, count = row - grouped_results[day.date()].append(row) - - print(grouped_results) - - for date in generate_date_range(start_date, days=days): - if date not in grouped_results: - grouped_results[date] = [] - - stats = {} - for day, rows in grouped_results.items(): - stats[day.strftime("%Y-%m-%d")] = statistics.format_statistics(rows) + stats = get_specific_days_stats(results, start_date, days=days) return stats @@ -744,19 +721,7 @@ def get_single_month_notification_stats_by_user(service_id, user_id): service_id, start_date, end_date, user_id ) - grouped_results = defaultdict(list) - for row in results: - notification_type, status, day, count = row - grouped_results[day.date()].append(row) - - for date in generate_date_range(start_date, end_date): - if date not in grouped_results: - grouped_results[date] = [] - - stats = {} - for day, rows in grouped_results.items(): - stats[day.strftime("%Y-%m-%d")] = statistics.format_statistics(rows) - + stats = get_specific_days_stats(results, start_date, end_date=end_date) return jsonify(stats) @@ -778,19 +743,7 @@ def get_single_month_notification_stats_for_service(service_id): results = dao_fetch_stats_for_service_from_days(service_id, start_date, end_date) - grouped_results = defaultdict(list) - for row in results: - notification_type, status, day, count = row - grouped_results[day.date()].append(row) - - for date in generate_date_range(start_date, end_date): - if date not in grouped_results: - grouped_results[date] = [] - - stats = {} - for day, rows in grouped_results.items(): - stats[day.strftime("%Y-%m-%d")] = statistics.format_statistics(rows) - + stats = get_specific_days_stats(results, start_date, end_date=end_date) return jsonify(stats) diff --git a/tests/app/service/test_statistics_rest.py b/tests/app/service/test_statistics_rest.py index 9769a678e..6d20cacc3 100644 --- a/tests/app/service/test_statistics_rest.py +++ b/tests/app/service/test_statistics_rest.py @@ -294,66 +294,6 @@ def test_get_monthly_notification_stats_returns_stats(admin_request, sample_serv } -# Test removed because new endpoint uses the view which combines this data -# @freeze_time("2016-06-05 12:00:00") -# def test_get_monthly_notification_stats_combines_todays_data_and_historic_stats( -# admin_request, sample_template -# ): -# create_ft_notification_status( -# datetime(2016, 5, 1, 12), -# template=sample_template, -# count=1, -# ) -# create_ft_notification_status( -# datetime(2016, 6, 1, 12), -# template=sample_template, -# notification_status=NotificationStatus.CREATED, -# count=2, -# ) # noqa - -# create_notification( -# sample_template, -# created_at=datetime(2016, 6, 5, 12), -# status=NotificationStatus.CREATED, -# ) -# create_notification( -# sample_template, -# created_at=datetime(2016, 6, 5, 12), -# status=NotificationStatus.DELIVERED, -# ) - -# # this doesn't get returned in the stats because it is old - it should be in ft_notification_status by now -# create_notification( -# sample_template, -# created_at=datetime(2016, 6, 4, 12), -# status=NotificationStatus.SENDING, -# ) - -# response = admin_request.get( -# "service.get_monthly_notification_stats", -# service_id=sample_template.service_id, -# year=2016, -# ) - -# assert len(response["data"]) == 6 # January to June -# assert response["data"]["2016-05"] == { -# NotificationType.SMS: { -# NotificationStatus.DELIVERED: 1, -# StatisticsType.REQUESTED: 1, -# }, -# NotificationType.EMAIL: {}, -# } -# assert response["data"]["2016-06"] == { -# NotificationType.SMS: { -# # combines the stats from the historic ft_notification_status and the current notifications -# NotificationStatus.CREATED: 3, -# NotificationStatus.DELIVERED: 1, -# StatisticsType.REQUESTED: 4, -# }, -# NotificationType.EMAIL: {}, -# } - - def test_get_monthly_notification_stats_ignores_test_keys( admin_request, sample_service ):