From d7c59fa8d79a3c0de298d25c8cbebc39a370564d Mon Sep 17 00:00:00 2001 From: Adam Shimali Date: Wed, 6 Apr 2016 15:48:04 +0100 Subject: [PATCH] Aggregation of template stats in admin app. Individual templates stats items fetched from admin. --- app/main/views/dashboard.py | 16 +++- .../views/dashboard/template-statistics.html | 7 +- tests/app/main/views/test_dashboard.py | 85 ++++++++++++++++++- 3 files changed, 97 insertions(+), 11 deletions(-) diff --git a/app/main/views/dashboard.py b/app/main/views/dashboard.py index 584dd6443..0130d7dc5 100644 --- a/app/main/views/dashboard.py +++ b/app/main/views/dashboard.py @@ -35,7 +35,7 @@ def service_dashboard(service_id): return redirect(url_for("main.tour", service_id=service_id, page=1)) statistics = statistics_api_client.get_statistics_for_service(service_id)['data'] - template_statistics = template_statistics_client.get_template_statistics_for_service(service_id) + template_statistics = aggregate_usage(template_statistics_client.get_template_statistics_for_service(service_id)) return render_template( 'views/dashboard/dashboard.html', @@ -53,7 +53,7 @@ def service_dashboard(service_id): def service_dashboard_updates(service_id): statistics = statistics_api_client.get_statistics_for_service(service_id)['data'] - template_statistics = template_statistics_client.get_template_statistics_for_service(service_id) + template_statistics = aggregate_usage(template_statistics_client.get_template_statistics_for_service(service_id)) return jsonify(**{ 'today': render_template( @@ -87,3 +87,15 @@ def add_rates_to(delivery_statistics): }) return latest_stats + + +def aggregate_usage(template_statistics): + import collections + stats = collections.OrderedDict() + for item in template_statistics: + stat = stats.get(item['template']['id']) + if stat: + stat['usage_count'] = stat['usage_count'] + item['usage_count'] + else: + stats[item['template']['id']] = item + return stats.values() diff --git a/app/templates/views/dashboard/template-statistics.html b/app/templates/views/dashboard/template-statistics.html index 9f6ba180d..2e6ae1e7c 100644 --- a/app/templates/views/dashboard/template-statistics.html +++ b/app/templates/views/dashboard/template-statistics.html @@ -1,9 +1,9 @@ {% from "components/table.html" import list_table, field, right_aligned_field_heading %} {% call(item, row_number) list_table( template_statistics, - caption="Recent templates used", + caption="Recent templates – last 7 days", empty_message='You haven’t sent any batch messages yet', - field_headings=['Template', 'Type', 'Date', right_aligned_field_heading('Usage')] + field_headings=['Template', 'Type', right_aligned_field_heading('Usage')] ) %} {% call field() %} @@ -13,9 +13,6 @@ {% call field() %} {{item.template.template_type}} {% endcall %} - {% call field() %} - {{item.day|format_date}} - {% endcall %} {% call field(align='right') %} {{ item.usage_count }} {% endcall %} diff --git a/tests/app/main/views/test_dashboard.py b/tests/app/main/views/test_dashboard.py index 78eabfcfe..b6fdc61e6 100644 --- a/tests/app/main/views/test_dashboard.py +++ b/tests/app/main/views/test_dashboard.py @@ -1,3 +1,4 @@ +import copy from flask import url_for from bs4 import BeautifulSoup @@ -6,34 +7,98 @@ from tests import validate_route_permission from tests.conftest import SERVICE_ONE_ID +stub_template_stats = [ + { + 'template': { + 'name': 'Brine Shrimp', + 'template_type': 'sms', + 'id': 1 + }, + 'id': '6005e192-4738-4962-beec-ebd982d0b03f', + 'day': '2016-04-06', + 'usage_count': 6, + 'service': '1491b86f-c950-48f5-bed1-2a55df027ecb' + }, + { + 'template': { + 'name': 'Pickle feet', + 'template_type': 'sms', + 'id': 2 + }, + 'id': '0bd529cd-a0fd-43e5-80ee-b95ef6b0d51f', + 'day': '2016-04-06', + 'usage_count': 6, + 'service': '1491b86f-c950-48f5-bed1-2a55df027ecb' + }, + { + 'template': { + 'name': 'Brine Shrimp', + 'template_type': 'sms', + 'id': 1 + }, + 'id': '24531628-ffff-4082-a443-9f6db5af83d9', + 'day': '2016-04-05', + 'usage_count': 7, + 'service': '1491b86f-c950-48f5-bed1-2a55df027ecb' + }, + { + 'template': { + 'name': 'Pickle feet', + 'template_type': 'sms', + 'id': 2 + }, + 'id': '0bd529cd-a0fd-43e5-80ee-b95ef6b0d51f', + 'day': '2016-03-06', + 'usage_count': 200, + 'service': '1491b86f-c950-48f5-bed1-2a55df027ecb' + }, +] + + def test_should_show_recent_templates_on_dashboard(app_, + mocker, api_user_active, mock_get_service, mock_get_service_templates, mock_get_service_statistics, - mock_get_template_statistics, mock_get_user, mock_get_user_by_email, mock_login, mock_get_jobs, mock_has_permissions): + + mock_template_stats = mocker.patch('app.template_statistics_client.get_template_statistics_for_service', + return_value=copy.deepcopy(stub_template_stats)) + with app_.test_request_context(): with app_.test_client() as client: client.login(api_user_active) response = client.get(url_for('main.service_dashboard', service_id=SERVICE_ONE_ID)) assert response.status_code == 200 - text = response.get_data(as_text=True) + response.get_data(as_text=True) mock_get_service_statistics.assert_called_once_with(SERVICE_ONE_ID) - mock_get_template_statistics.assert_called_once_with(SERVICE_ONE_ID) + mock_template_stats.assert_called_once_with(SERVICE_ONE_ID) page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') headers = [header.text.strip() for header in page.find_all('h2')] assert 'Test Service' in headers assert 'Sent today' in headers template_usage_headers = [th.text.strip() for th in page.thead.find_all('th')] - for th in ['Template', 'Type', 'Date', 'Usage']: + for th in ['Template', 'Type', 'Usage']: assert th in template_usage_headers + table_rows = page.tbody.find_all('tr') + + assert len(table_rows) == 2 + first_row = page.tbody.find_all('tr')[0] + table_data = first_row.find_all('td') + assert len(table_data) == 3 + assert table_data[2].text.strip() == '13' + + second_row = page.tbody.find_all('tr')[1] + table_data = second_row.find_all('td') + assert len(table_data) == 3 + assert table_data[2].text.strip() == '206' def _test_dashboard_menu(mocker, app_, usr, service, permissions): @@ -197,3 +262,15 @@ def test_route_for_service_permissions(mocker, ['view_activity'], api_user_active, service_one) + + +def test_aggregate_template_stats(): + from app.main.views.dashboard import aggregate_usage + expected = aggregate_usage(copy.deepcopy(stub_template_stats)) + + assert len(expected) == 2 + for item in expected: + if item['template']['id'] == 1: + assert item['usage_count'] == 13 + elif item['template']['id'] == 2: + assert item['usage_count'] == 206