diff --git a/app/main/views/platform_admin.py b/app/main/views/platform_admin.py index 6c8a0923c..260a2e486 100644 --- a/app/main/views/platform_admin.py +++ b/app/main/views/platform_admin.py @@ -381,6 +381,46 @@ def get_daily_volumes(): return render_template('views/platform-admin/daily-volumes-report.html', form=form) +@main.route("/platform-admin/reports/daily-sms-provider-volumes-report", methods=['GET', 'POST']) +@user_is_platform_admin +def get_daily_sms_provider_volumes(): + form = BillingReportDateFilterForm() + + if form.validate_on_submit(): + start_date = form.start_date.data + end_date = form.end_date.data + headers = [ + "day", + "provider", + "sms totals", + "sms fragment totals", + "sms chargeable units", + "sms cost", + ] + result = billing_api_client.get_data_for_daily_sms_provider_volumes_report(start_date, end_date) + + rows = [ + [ + r["day"], + r["provider"], + r["sms_totals"], + r["sms_fragment_totals"], + r["sms_chargeable_units"], + r["sms_cost"] + ] + for r in result + ] + if rows: + return Spreadsheet.from_rows([headers] + rows).as_csv_data, 200, { + 'Content-Type': 'text/csv; charset=utf-8', + 'Content-Disposition': + f'attachment; filename="Daily SMS provider volumes report from {start_date} to {end_date}.csv"' + } + else: + flash('No results for dates') + return render_template('views/platform-admin/daily-sms-provider-volumes-report.html', form=form) + + @main.route("/platform-admin/complaints") @user_is_platform_admin def platform_admin_list_complaints(): diff --git a/app/navigation.py b/app/navigation.py index a364fd4d4..6053b960d 100644 --- a/app/navigation.py +++ b/app/navigation.py @@ -95,6 +95,7 @@ class HeaderNavigation(Navigation): 'notifications_sent_by_service', 'get_billing_report', 'get_daily_volumes', + 'get_daily_sms_provider_volumes', 'get_volumes_by_service', 'organisations', 'platform_admin', diff --git a/app/notify_client/billing_api_client.py b/app/notify_client/billing_api_client.py index 08b5ce52c..44634ff4e 100644 --- a/app/notify_client/billing_api_client.py +++ b/app/notify_client/billing_api_client.py @@ -55,5 +55,14 @@ class BillingAPIClient(NotifyAdminAPIClient): 'end_date': str(end_date), }) + def get_data_for_daily_sms_provider_volumes_report(self, start_date, end_date): + return self.get( + url='/platform-stats/daily-sms-provider-volumes-report', + params={ + 'start_date': str(start_date), + 'end_date': str(end_date), + } + ) + billing_api_client = BillingAPIClient() diff --git a/app/templates/views/platform-admin/daily-sms-provider-volumes-report.html b/app/templates/views/platform-admin/daily-sms-provider-volumes-report.html new file mode 100644 index 000000000..73b3ca4ae --- /dev/null +++ b/app/templates/views/platform-admin/daily-sms-provider-volumes-report.html @@ -0,0 +1,47 @@ +{% extends "views/platform-admin/_base_template.html" %} +{% from "components/form.html" import form_wrapper %} +{% from "components/table.html" import mapping_table, row, text_field %} + +{% block per_page_title %} + Daily SMS provider volumes Report +{% endblock %} + +{% block platform_admin_content %} + +

+ Daily SMS provider volumes Report +

+ + {% call form_wrapper() %} + {{ form.start_date(param_extensions={"hint": {"text": "Use the format YYYY-MM-DD"}}) }} + {{ form.end_date(param_extensions={"hint": {"text": "Use the format YYYY-MM-DD"}}) }} + {{ page_footer('Download report') }} + {% endcall %} + +

+ Data included in the report +

+
+ {% call mapping_table( + caption='Descriptions of daily SMS provider volumes data', + field_headings=['Name', 'Description'], + field_headings_visible=True, + caption_visible=False + ) %} + {% for message_length, description in [ + ('day', 'The whole business day in BST'), + ('provider', 'The SMS provider'), + ('sms totals', 'The number of text messages sent'), + ('sms fragments', 'The number of text message fragments sent'), + ('sms chargeable units', 'The number of text message fragments sent times the rate multiplier'), + ('sms cost', 'The cost of text messages sent'), + ] %} + {% call row() %} + {{ text_field(message_length) }} + {{ text_field(description | safe) }} + {% endcall %} + {% endfor %} + {% endcall %} +
+ +{% endblock %} diff --git a/app/templates/views/platform-admin/reports.html b/app/templates/views/platform-admin/reports.html index dda3f18ff..8dd36ffef 100644 --- a/app/templates/views/platform-admin/reports.html +++ b/app/templates/views/platform-admin/reports.html @@ -25,4 +25,7 @@

Daily volumes Report

+

+ Daily SMS provider volumes Report +

{% endblock %} diff --git a/tests/app/main/views/test_platform_admin.py b/tests/app/main/views/test_platform_admin.py index b106d4255..e6b0e8f2b 100644 --- a/tests/app/main/views/test_platform_admin.py +++ b/tests/app/main/views/test_platform_admin.py @@ -1113,3 +1113,46 @@ def test_get_daily_volumes_report_when_calls_api_and_download_data( '\r\n' ) + + +def test_get_daily_sms_provider_volumes_report_when_calls_api_and_download_data( + client_request, + platform_admin_user, + mocker +): + mocker.patch( + "app.main.views.platform_admin.billing_api_client.get_data_for_daily_sms_provider_volumes_report", + return_value=[{ + "day": '2019-01-01', + "provider": 'foo', + "sms_totals": 20, + "sms_fragment_totals": 40, + "sms_chargeable_units": 60, + "sms_cost": 80, + }] + ) + + client_request.login(platform_admin_user) + response = client_request.post_response( + 'main.get_daily_sms_provider_volumes', + _data={'start_date': '2019-01-01', 'end_date': '2019-03-31'}, + _expected_status=200, + ) + + assert response.content_type == 'text/csv; charset=utf-8' + assert response.headers['Content-Disposition'] == ( + 'attachment; filename="Daily SMS provider volumes report from {} to {}.csv"'.format('2019-01-01', '2019-03-31') + ) + + assert response.get_data(as_text=True) == ( + "day,provider,sms totals,sms fragment totals,sms chargeable units,sms cost\r\n" + + + '2019-01-01,' + + 'foo,' + + '20,' + + '40,' + + '60,' + + '80' + + '\r\n' + ) diff --git a/tests/app/test_navigation.py b/tests/app/test_navigation.py index 06eccdd28..5b6d1eda5 100644 --- a/tests/app/test_navigation.py +++ b/tests/app/test_navigation.py @@ -132,6 +132,7 @@ EXCLUDED_ENDPOINTS = tuple(map(Navigation.get_endpoint_with_blueprint, { 'forgot_password', 'get_billing_report', 'get_daily_volumes', + 'get_daily_sms_provider_volumes', 'get_volumes_by_service', 'get_example_csv', 'get_notifications_as_json',