diff --git a/app/__init__.py b/app/__init__.py index 813e6e38f..46554c32e 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -112,6 +112,7 @@ def register_blueprint(application): from app.billing.rest import billing_blueprint from app.organisation.rest import organisation_blueprint from app.organisation.invite_rest import organisation_invite_blueprint + from app.complaint.complaint_rest import complaint_blueprint service_blueprint.before_request(requires_admin_auth) application.register_blueprint(service_blueprint, url_prefix='/service') @@ -188,6 +189,9 @@ def register_blueprint(application): organisation_invite_blueprint.before_request(requires_admin_auth) application.register_blueprint(organisation_invite_blueprint) + complaint_blueprint.before_request(requires_admin_auth) + application.register_blueprint(complaint_blueprint) + def register_v2_blueprints(application): from app.v2.inbound_sms.get_inbound_sms import v2_inbound_sms_blueprint as get_inbound_sms diff --git a/app/complaint/__init__.py b/app/complaint/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/app/complaint/complaint_rest.py b/app/complaint/complaint_rest.py new file mode 100644 index 000000000..f59b12457 --- /dev/null +++ b/app/complaint/complaint_rest.py @@ -0,0 +1,16 @@ +from flask import Blueprint, jsonify +from sqlalchemy import desc + +from app.errors import register_errors +from app.models import Complaint + +complaint_blueprint = Blueprint('complaint', __name__, url_prefix='/complaint') + +register_errors(complaint_blueprint) + + +@complaint_blueprint.route('', methods=['GET']) +def get_all_complaints(): + complaints = Complaint.query.order_by(desc(Complaint.created_at)).all() + + return jsonify([x.serialize() for x in complaints]), 200 diff --git a/app/models.py b/app/models.py index 4d1802582..20dd6b1ab 100644 --- a/app/models.py +++ b/app/models.py @@ -1819,6 +1819,7 @@ class FactNotificationStatus(db.Model): class Complaint(db.Model): __tablename__ = 'complaints' + id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) notification_id = db.Column(UUID(as_uuid=True), db.ForeignKey('notification_history.id'), index=True, nullable=False) @@ -1828,3 +1829,15 @@ class Complaint(db.Model): complaint_type = db.Column(db.Text, nullable=True) complaint_date = db.Column(db.DateTime, nullable=True) created_at = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow) + + def serialize(self): + return { + 'id': str(self.id), + 'notification_id': str(self.notification_id), + 'service_id': str(self.service_id), + 'service_name': self.service.name, + 'ses_feedback_id': str(self.ses_feedback_id), + 'complaint_type': self.complaint_type, + 'complaint_date': self.complaint_date.strftime(DATETIME_FORMAT) if self.complaint_date else None, + 'created_at': self.created_at.strftime(DATETIME_FORMAT), + } diff --git a/tests/app/complaint/__init__.py b/tests/app/complaint/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/app/complaint/test_complaint_rest.py b/tests/app/complaint/test_complaint_rest.py new file mode 100644 index 000000000..d3b352fca --- /dev/null +++ b/tests/app/complaint/test_complaint_rest.py @@ -0,0 +1,24 @@ +import json + +from tests import create_authorization_header +from tests.app.db import create_complaint, create_service, create_template, create_notification + + +def test_get_all_complaints_returns_list_for_multiple_services_and_complaints(client, notify_db_session): + service=create_service(service_name='service1') + template = create_template(service=service) + notification = create_notification(template=template) + complaint_1 = create_complaint() # default service + complaint_2 = create_complaint(service=service, notification=notification) + + response = client.get('/complaint', headers=[create_authorization_header()]) + + assert response.status_code == 200 + assert json.loads(response.get_data(as_text=True)) == [complaint_2.serialize(), complaint_1.serialize()] + + +def test_get_all_complaints_returns_empty_list(client): + response = client.get('/complaint', headers=[create_authorization_header()]) + + assert response.status_code == 200 + assert json.loads(response.get_data(as_text=True)) == [] diff --git a/tests/app/dao/test_complaint_dao.py b/tests/app/dao/test_complaint_dao.py index 92478cc33..d1acc93f7 100644 --- a/tests/app/dao/test_complaint_dao.py +++ b/tests/app/dao/test_complaint_dao.py @@ -22,7 +22,7 @@ def test_fetch_complaint_by_service_returns_one(sample_service, sample_email_not assert complaints[0] == complaint -def test_fetch_complaint_by_service_returns_empty_list(sample_service, sample_email_notification): +def test_fetch_complaint_by_service_returns_empty_list(sample_service): complaints = fetch_complaints_by_service(service_id=sample_service.id) assert len(complaints) == 0 diff --git a/tests/app/db.py b/tests/app/db.py index 76fa27895..93ff83579 100644 --- a/tests/app/db.py +++ b/tests/app/db.py @@ -34,7 +34,8 @@ from app.models import ( AnnualBilling, LetterRate, InvitedOrganisationUser, - FactBilling + FactBilling, + Complaint ) from app.dao.users_dao import save_model_user from app.dao.notifications_dao import ( @@ -564,6 +565,27 @@ def create_ft_billing(bst_date, return data +def create_complaint(service=None, + notification=None): + + if not service: + service=create_service() + if not notification: + template = create_template(service=service, template_type='email') + notification = create_notification(template=template) + + + complaint = Complaint(notification_id=notification.id, + service_id=service.id, + ses_feedback_id=str(uuid.uuid4()), + complaint_type='abuse', + complaint_date=datetime.utcnow() + ) + db.session.add(complaint) + db.session.commit() + return complaint + + def ses_complaint_callback_malformed_message_id(): return '{\n "Type" : "Notification",\n "msgId" : "ref1",' \ '\n "TopicArn" : "arn:aws:sns:eu-west-1:123456789012:testing",' \