When someone complains about an email from the platform we get a callback from SES.

A new platform admin page Email complaints has been added to surface those complaints.
Eventually the complaints will be visible to the services so they can remove the email address from their mailing list.

Next thing to implement is "x email complaints" warning on the platform admin summary page.
This commit is contained in:
Rebecca Law
2018-06-06 15:22:48 +01:00
parent 217cf9abd4
commit 84445d154d
8 changed files with 108 additions and 2 deletions

View File

@@ -58,6 +58,7 @@ from app.notify_client.org_invite_api_client import OrgInviteApiClient
from app.notify_client.letter_jobs_client import LetterJobsClient
from app.notify_client.inbound_number_client import InboundNumberClient
from app.notify_client.billing_api_client import BillingAPIClient
from app.notify_client.complaint_api_client import ComplaintApiClient
from app.commands import setup_commands
from app.utils import get_cdn_domain
from app.utils import gmt_timezones
@@ -84,6 +85,7 @@ zendesk_client = ZendeskClient()
letter_jobs_client = LetterJobsClient()
inbound_number_client = InboundNumberClient()
billing_api_client = BillingAPIClient()
complaint_api_client = ComplaintApiClient()
# The current service attached to the request stack.
current_service = LocalProxy(partial(_lookup_req_object, 'service'))
@@ -128,6 +130,7 @@ def create_app(application):
letter_jobs_client.init_app(application)
inbound_number_client.init_app(application)
billing_api_client.init_app(application)
complaint_api_client.init_app(application)
login_manager.init_app(application)
login_manager.login_view = 'main.sign_in'

View File

@@ -4,7 +4,7 @@ from datetime import datetime
from flask import render_template, request
from flask_login import login_required
from app import service_api_client
from app import complaint_api_client, service_api_client
from app.main import main
from app.main.forms import DateFilterForm
from app.statistics_utils import get_formatted_percentage
@@ -70,6 +70,18 @@ def platform_admin_services():
)
@main.route("/platform-admin/complaints")
@login_required
@user_is_platform_admin
def platform_admin_list_complaints():
complaints = complaint_api_client.get_all_complaints()
return render_template(
'views/platform-admin/complaints.html',
complaints=complaints,
page_title='All Complaints',
)
def sum_service_usage(service):
total = 0
for notification_type in service['statistics'].keys():

View File

@@ -84,6 +84,7 @@ class HeaderNavigation(Navigation):
'update_email_branding',
'view_provider',
'view_providers',
'platform_admin_list_complaints',
},
'sign-in': {
'sign_in',
@@ -418,6 +419,7 @@ class MainNavigation(Navigation):
'organisation_settings',
'organisations',
'platform_admin',
'platform_admin_list_complaints',
'pricing',
'privacy',
'public_agreement',
@@ -586,6 +588,7 @@ class OrgNavigation(Navigation):
'old_using_notify',
'organisations',
'platform_admin',
'platform_admin_list_complaints',
'pricing',
'privacy',
'public_agreement',

View File

@@ -0,0 +1,11 @@
from app.notify_client import NotifyAdminAPIClient
class ComplaintApiClient(NotifyAdminAPIClient):
# Fudge assert in the super __init__ so
# we can set those variables later.
def __init__(self):
super().__init__("a" * 73, "b")
def get_all_complaints(self):
return self.get('/complaint')

View File

@@ -19,7 +19,8 @@
('Providers', url_for('main.view_providers')),
('Email branding', url_for('main.email_branding')),
('Letter jobs', url_for('main.letter_jobs')),
('Inbound SMS numbers', url_for('main.inbound_sms_admin'))
('Inbound SMS numbers', url_for('main.inbound_sms_admin')),
('Email Complaints', url_for('main.platform_admin_list_complaints'))
] %}
<li>
<a href="{{ url }}">

View File

@@ -0,0 +1,36 @@
{% extends "views/platform-admin/_base_template.html" %}
{% from "components/page-footer.html" import page_footer %}
{% from "components/table.html" import list_table, field, text_field, link_field, right_aligned_field_heading, hidden_field_heading %}
{% block per_page_title %}
{{ page_title|capitalize }}
{% endblock %}
{% block platform_admin_content %}
<h1 class="heading-large">
Email complaints
</h1>
{% call(item, row_number) list_table(
complaints,
caption="Complaints",
caption_visible=False,
empty_message='No complaints',
field_headings=['Notification Id', 'Service', 'Complaint type', 'Complaint Date'],
field_headings_visible=True
) %}
{{ link_field(item.notification_id, url_for('main.view_notification', service_id=item.service_id, notification_id=item.notification_id)) }}
{{ link_field(item.service_name, url_for('main.service_dashboard', service_id=item.service_id)) }}
{{ text_field(item.complaint_type) }}
{{ text_field(item.complaint_date|format_datetime_short) }}
{% endcall %}
{% endblock %}

View File

@@ -1,4 +1,5 @@
import datetime
import uuid
from unittest.mock import ANY
import pytest
@@ -637,3 +638,32 @@ def test_sum_service_usage_with_zeros(fake_uuid):
sms_failed=0
)
assert sum_service_usage(service) == 0
def test_platform_admin_list_complaints(
client,
platform_admin_user,
mocker
):
mock_get_user(mocker, user=platform_admin_user)
client.login(platform_admin_user)
complaint = {
'id': str(uuid.uuid4()),
'notification_id': str(uuid.uuid4()),
'service_id': str(uuid.uuid4()),
'service_name': 'Sample service',
'ses_feedback_id': 'Some ses id',
'complaint_type': 'abuse',
'complaint_date': '2018-06-05T13:50:30.012354',
'created_at': '2018-06-05T13:50:30.012354',
}
mock = mocker.patch('app.complaint_api_client.get_all_complaints',
return_value=[complaint])
client.login(platform_admin_user)
response = client.get(url_for('main.platform_admin_list_complaints'))
assert response.status_code == 200
resp_data = response.get_data(as_text=True)
assert 'Email complaints' in resp_data
mock.assert_called_once()

View File

@@ -0,0 +1,10 @@
from app import ComplaintApiClient
def test_get_all_complaints(mocker):
client = ComplaintApiClient()
mock = mocker.patch('app.notify_client.complaint_api_client.ComplaintApiClient.get')
client.get_all_complaints()
mock.assert_called_once_with('/complaint')