Repository: akvo/akvo-rsr

Issue:
Feature Request: Demo schedule request endpoint
### What are you trying to do?

The product manager wants to be notified when someone requests a schedule for a demo.

### Describe the solution you'd like

Send email notification.

### Have you consider alternatives?

_No response_

### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/akvo/rest/urls.py b/akvo/rest/urls.py
--- a/akvo/rest/urls.py
+++ b/akvo/rest/urls.py
@@ -265,6 +265,9 @@
     url(r'v1/project_published_search$',
         views.project_published_search,
         name='project_published_search'),
+    url(r'v1/demo_request$',
+        views.demo_request,
+        name='demo_request'),
 )
 
 # GeoJSON views
diff --git a/akvo/rest/views/__init__.py b/akvo/rest/views/__init__.py
--- a/akvo/rest/views/__init__.py
+++ b/akvo/rest/views/__init__.py
@@ -110,6 +110,7 @@
 from .project_overview import project_results, project_result_overview, project_indicator_overview
 from .program_results_geo import get_program_results_geo
 from .project_enumerators import assignment_send, project_enumerators
+from .demo_request import demo_request
 
 __all__ = [
     'assignment_send',
@@ -252,4 +253,5 @@
     'change_user_roles',
     'RawProjectHierarchyViewSet',
     'managed_employments',
+    'demo_request',
 ]
diff --git a/akvo/rest/views/demo_request.py b/akvo/rest/views/demo_request.py
new file mode 100644
--- /dev/null
+++ b/akvo/rest/views/demo_request.py
@@ -0,0 +1,41 @@
+# Akvo RSR is covered by the GNU Affero General Public License.
+
+# See more details in the license.txt file located at the root folder of the Akvo RSR module.
+# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+
+from akvo.utils import rsr_send_mail
+from django.conf import settings
+from rest_framework import serializers
+from rest_framework import status
+from rest_framework.response import Response
+from rest_framework.decorators import api_view
+
+
+@api_view(['POST'])
+def demo_request(request):
+    serializer = DemoRequestSerializer(data=request.data)
+    if not serializer.is_valid():
+        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+    data = serializer.validated_data
+    mail_to = getattr(settings, 'RSR_DEMO_REQUEST_TO_EMAILS', [])
+    if mail_to:
+        rsr_send_mail(
+            mail_to,
+            subject='demo_request/subject.txt',
+            message='demo_request/message.txt',
+            subject_context=data,
+            msg_context=data
+        )
+    return Response({'message': 'success'})
+
+
+class DemoRequestSerializer(serializers.Serializer):
+    first_name = serializers.CharField()
+    last_name = serializers.CharField()
+    email = serializers.EmailField()
+    phone = serializers.CharField(required=False, allow_blank=True)
+    akvo_hub = serializers.CharField()
+    message = serializers.CharField()
+
+    class Meta:
+        fields = '__all__'


Test patch:
diff --git a/akvo/rsr/tests/rest/test_demo_request.py b/akvo/rsr/tests/rest/test_demo_request.py
new file mode 100644
--- /dev/null
+++ b/akvo/rsr/tests/rest/test_demo_request.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 -*-
+
+# Akvo RSR is covered by the GNU Affero General Public License.
+
+# See more details in the license.txt file located at the root folder of the Akvo RSR module.
+# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.
+
+import json
+from django.core import mail
+from django.test import override_settings
+from akvo.rsr.tests.base import BaseTestCase
+
+
+class DemoRequestTestCase(BaseTestCase):
+    def get_csrf_token(self):
+        response = self.c.get('/auth/csrf-token/')
+        return response.client.cookies['csrftoken'].value
+
+    def post_request(self, data):
+        csrftoken = self.get_csrf_token()
+        return self.c.post('/rest/v1/demo_request', json.dumps(data), content_type='application/json', HTTP_X_CSRFTOKEN=csrftoken)
+
+    def test_required_fields(self):
+        response = self.post_request({})
+        self.assertEqual(400, response.status_code)
+        data = response.data
+        self.assertEqual({
+            ('first_name', 'This field is required.'),
+            ('last_name', 'This field is required.'),
+            ('email', 'This field is required.'),
+            ('akvo_hub', 'This field is required.'),
+            ('message', 'This field is required.')
+        }, {(field, str(error)) for field, errors in data.items() for error in errors})
+
+    def test_blank_fields(self):
+        response = self.post_request({
+            'first_name': '',
+            'last_name': '',
+            'email': '',
+            'phone': '',
+            'akvo_hub': '',
+            'message': ''
+        })
+        self.assertEqual(400, response.status_code)
+        data = response.data
+        self.assertEqual({
+            ('first_name', 'This field may not be blank.'),
+            ('last_name', 'This field may not be blank.'),
+            ('email', 'This field may not be blank.'),
+            ('akvo_hub', 'This field may not be blank.'),
+            ('message', 'This field may not be blank.')
+        }, {(field, str(error)) for field, errors in data.items() for error in errors})
+
+    def test_invalid_email_address(self):
+        response = self.post_request({
+            'first_name': 'John',
+            'last_name': 'Doe',
+            'email': 'johndoe-example.com',
+            'akvo_hub': 'Akvo Asia',
+            'message': 'I need to learn more about RSR'
+        })
+        self.assertEqual(400, response.status_code)
+        data = response.data
+        self.assertEqual({
+            ('email', 'Enter a valid email address.'),
+        }, {(field, str(error)) for field, errors in data.items() for error in errors})
+
+    def test_sent_mail(self):
+        recipient = ['admin@akvo.org']
+        payload = {
+            'first_name': 'John',
+            'last_name': 'Doe',
+            'email': 'johndoe@example.com',
+            'phone': '123456789',
+            'akvo_hub': 'Akvo Asia',
+            'message': 'I need to learn more about RSR'
+        }
+        with override_settings(RSR_DEMO_REQUEST_TO_EMAILS=recipient):
+            response = self.post_request(payload)
+        self.assertEqual(200, response.status_code)
+        self.assertEqual(1, len(mail.outbox))
+        msg = mail.outbox[0]
+        self.assertEqual(recipient, msg.to)
+        self.assertIn(payload['first_name'], msg.body)
+        self.assertIn(payload['last_name'], msg.body)
+        self.assertIn(payload['email'], msg.body)
+        self.assertIn(payload['email'], msg.body)
+        self.assertIn(payload['akvo_hub'], msg.body)
+        self.assertIn(payload['message'], msg.body)