Report for total notifications sent per day for each channel.

Daily volumes report: total volumes across the platform aggregated by whole business day (bst_date)
Volumes by service report: total volumes per service aggregated by the date range given.

NB: start and end dates are inclusive
This commit is contained in:
Rebecca Law
2022-03-07 14:30:11 +00:00
parent f827a825a1
commit 971cb745c9
8 changed files with 204 additions and 0 deletions

View File

@@ -313,6 +313,74 @@ def get_billing_report():
return render_template('views/platform-admin/get-billing-report.html', form=form)
@main.route("/platform-admin/reports/volumes-by-service", methods=['GET', 'POST'])
@user_is_platform_admin
def get_volumes_by_service():
form = BillingReportDateFilterForm()
if form.validate_on_submit():
start_date = form.start_date.data
end_date = form.end_date.data
headers = [
"organisation_id", "organisation_name", "service_id", "service_name",
"free_allowance", "sms_notifications", "sms chargeable units", "email_totals",
"letter_totals", "letter_cost", "letter_sheet_totals"
]
result = billing_api_client.get_data_for_volumes_by_service_report(start_date, end_date)
rows = [
[
r["organisation_id"], r["organisation_name"], r["service_id"], r["service_name"],
r["free_allowance"], r["sms_notifications"], r["sms_chargeable_units"], r["email_totals"],
r["letter_totals"], r["letter_cost"], r["letter_sheet_totals"]
]
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': 'attachment; filename="Volumes by service report from {} to {}.csv"'.format(
start_date, end_date
)
}
else:
flash('No results for dates')
return render_template('views/platform-admin/volumes-by-service-report.html', form=form)
@main.route("/platform-admin/reports/daily-volumes-report", methods=['GET', 'POST'])
@user_is_platform_admin
def get_daily_volumes():
form = BillingReportDateFilterForm()
if form.validate_on_submit():
start_date = form.start_date.data
end_date = form.end_date.data
headers = [
"day", "sms totals", "sms fragment totals", "sms chargeable units",
"email totals", "letter totals", "letter sheet totals"
]
result = billing_api_client.get_data_for_daily_volumes_report(start_date, end_date)
rows = [
[
r["day"], r["sms_totals"], r["sms_fragment_totals"], r["sms_chargeable_units"],
r["email_totals"], r["letter_totals"], r["letter_sheet_totals"]
]
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': 'attachment; filename="Daily volumes report from {} to {}.csv"'.format(
start_date, end_date
)
}
else:
flash('No results for dates')
return render_template('views/platform-admin/daily-volumes-report.html', form=form)
@main.route("/platform-admin/complaints")
@user_is_platform_admin
def platform_admin_list_complaints():

View File

@@ -92,6 +92,8 @@ class HeaderNavigation(Navigation):
'live_services_csv',
'notifications_sent_by_service',
'get_billing_report',
'get_daily_volumes',
'get_volumes_by_service',
'organisations',
'platform_admin',
'platform_admin_list_complaints',

View File

@@ -41,5 +41,19 @@ class BillingAPIClient(NotifyAdminAPIClient):
'end_date': str(end_date),
})
def get_data_for_volumes_by_service_report(self, start_date, end_date):
return self.get(url='/platform-stats/volumes-by-service',
params={
'start_date': str(start_date),
'end_date': str(end_date),
})
def get_data_for_daily_volumes_report(self, start_date, end_date):
return self.get(url='/platform-stats/daily-volumes-report',
params={
'start_date': str(start_date),
'end_date': str(end_date),
})
billing_api_client = BillingAPIClient()

View File

@@ -0,0 +1,48 @@
{% 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 volumes report
{% endblock %}
{% block platform_admin_content %}
<h1 class="heading-large">
Daily volumes Report
</h1>
{% 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 %}
<h2 class="heading-medium">
Data included in the report
</h2>
<div class="bottom-gutter-3-2">
{% call mapping_table(
caption='Descriptions of daily volumes data',
field_headings=['Name', 'Description'],
field_headings_visible=True,
caption_visible=False
) %}
{% for message_length, charge in [
('day', 'The whole business day in BST.'),
('sms totals', 'The number of text messages sent'),
('sms chargeable units', 'The number of text message fragments sent'),
('sms_fragments_times_multiplier', 'The number of text message fragments sent times the rate multiplier'),
('email totals', 'The number of emails sent'),
('letter totals', 'The number of letters sent'),
('letter sheet totals', The number of sheets sent)
] %}
{% call row() %}
{{ text_field(message_length) }}
{{ text_field(charge | safe) }}
{% endcall %}
{% endfor %}
{% endcall %}
</div>
{% endblock %}

View File

@@ -19,4 +19,10 @@
<p class="govuk-body">
<a class="govuk-link govuk-link--no-visited-state" href="{{ url_for('main.get_billing_report') }}">Billing Report</a>
</p>
<p class="govuk-body">
<a class="govuk-link govuk-link--no-visited-state" href="{{ url_for('main.get_volumes_by_service') }}">Volumes by service Report</a>
</p>
<p class="govuk-body">
<a class="govuk-link govuk-link--no-visited-state" href="{{ url_for('main.get_daily_volumes') }}">Daily volumes Report</a>
</p>
{% endblock %}

View File

@@ -0,0 +1,46 @@
{% 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 %}
Volumes by service report
{% endblock %}
{% block platform_admin_content %}
<h1 class="heading-large">
Volumes by service Report
</h1>
{% 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 %}
<h2 class="heading-medium">
Data included in the report
</h2>
<div class="bottom-gutter-3-2">
{% call mapping_table(
caption='Descriptions of volumes by service data',
field_headings=['Name', 'Description'],
field_headings_visible=True,
caption_visible=False
) %}
{% for message_length, charge in [
('free allowance', 'Free allowance set for the service. This is the latest free allowance for the date range given'),
('sms notifications', 'The number of text messages sent by the service.'),
('sms volume', 'The number of text message fragments times the rate multiplier sent by the service.'),
('email totals', 'The number of emails sent by a service'),
('letter totals', 'The number of letters sent by a service'),
] %}
{% call row() %}
{{ text_field(message_length) }}
{{ text_field(charge | safe) }}
{% endcall %}
{% endfor %}
{% endcall %}
</div>
{% endblock %}

View File

@@ -41,3 +41,21 @@ def test_post_free_sms_fragment_limit_for_year_endpoint(mocker, api_user_active)
url='/service/{}/billing/free-sms-fragment-limit'.format(service_id),
data=sms_limit_data
)
def test_get_data_for_volumes_by_service_report(mocker, api_user_active):
mock_get = mocker.patch('app.notify_client.billing_api_client.BillingAPIClient.get')
client = BillingAPIClient()
client.get_data_for_volumes_by_service_report('2022-03-01', '2022-03-31')
mock_get.assert_called_once_with(url='/platform-stats/volumes-by-service',
params={'start_date': '2022-03-01', 'end_date': '2022-03-31'})
def test_get_data_for_daily_volumes_report(mocker, api_user_active):
mock_get = mocker.patch('app.notify_client.billing_api_client.BillingAPIClient.get')
client = BillingAPIClient()
client.get_data_for_daily_volumes_report('2022-03-01', '2022-03-31')
mock_get.assert_called_once_with(url='/platform-stats/daily-volumes-report',
params={'start_date': '2022-03-01', 'end_date': '2022-03-31'})

View File

@@ -131,6 +131,8 @@ EXCLUDED_ENDPOINTS = tuple(map(Navigation.get_endpoint_with_blueprint, {
'find_users_by_email',
'forgot_password',
'get_billing_report',
'get_daily_volumes',
'get_volumes_by_service',
'get_example_csv',
'get_notifications_as_json',
'get_started',