Commit 7493c11e by Asad Iqbal Committed by GitHub

Merge pull request #14890 from edx/asadiqbal08/ENT-188

ENT-188 Enterprise Learner support requests from LMS to Zendesk queue
parents c3d0a50d 8cea65b2
...@@ -1087,6 +1087,9 @@ OPTIONAL_APPS = ( ...@@ -1087,6 +1087,9 @@ OPTIONAL_APPS = (
# Organizations App (http://github.com/edx/edx-organizations) # Organizations App (http://github.com/edx/edx-organizations)
'organizations', 'organizations',
# Enterprise App (http://github.com/edx/edx-enterprise)
'enterprise',
) )
...@@ -1266,6 +1269,8 @@ USER_TASKS_MAX_AGE = timedelta(days=7) ...@@ -1266,6 +1269,8 @@ USER_TASKS_MAX_AGE = timedelta(days=7)
############## Settings for the Enterprise App ###################### ############## Settings for the Enterprise App ######################
ENTERPRISE_ENROLLMENT_API_URL = LMS_ROOT_URL + "/api/enrollment/v1/" ENTERPRISE_ENROLLMENT_API_URL = LMS_ROOT_URL + "/api/enrollment/v1/"
ENTERPRISE_SERVICE_WORKER_USERNAME = 'enterprise_worker'
ENTERPRISE_API_CACHE_TIMEOUT = 3600 # Value is in seconds
############## Settings for the Discovery App ###################### ############## Settings for the Discovery App ######################
......
...@@ -7,8 +7,11 @@ from django.test.client import RequestFactory ...@@ -7,8 +7,11 @@ from django.test.client import RequestFactory
from django.test.utils import override_settings from django.test.utils import override_settings
from smtplib import SMTPException from smtplib import SMTPException
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
from openedx.features.enterprise_support.tests.mixins.enterprise import EnterpriseServiceMockMixin
from util import views from util import views
from zendesk import ZendeskError from zendesk import ZendeskError
import httpretty
import json import json
import mock import mock
from ddt import ddt, data, unpack from ddt import ddt, data, unpack
...@@ -17,7 +20,11 @@ from student.tests.test_configuration_overrides import fake_get_value ...@@ -17,7 +20,11 @@ from student.tests.test_configuration_overrides import fake_get_value
from student.tests.factories import CourseEnrollmentFactory from student.tests.factories import CourseEnrollmentFactory
TEST_SUPPORT_EMAIL = "support@example.com" TEST_SUPPORT_EMAIL = "support@example.com"
TEST_ZENDESK_CUSTOM_FIELD_CONFIG = {"course_id": 1234, "enrollment_mode": 5678} TEST_ZENDESK_CUSTOM_FIELD_CONFIG = {
"course_id": 1234,
"enrollment_mode": 5678,
'enterprise_customer_name': 'enterprise_customer_name'
}
TEST_REQUEST_HEADERS = { TEST_REQUEST_HEADERS = {
"HTTP_REFERER": "test_referer", "HTTP_REFERER": "test_referer",
"HTTP_USER_AGENT": "test_user_agent", "HTTP_USER_AGENT": "test_user_agent",
...@@ -44,11 +51,12 @@ def fake_support_backend_values(name, default=None): # pylint: disable=unused-a ...@@ -44,11 +51,12 @@ def fake_support_backend_values(name, default=None): # pylint: disable=unused-a
ZENDESK_URL="dummy", ZENDESK_URL="dummy",
ZENDESK_USER="dummy", ZENDESK_USER="dummy",
ZENDESK_API_KEY="dummy", ZENDESK_API_KEY="dummy",
ZENDESK_CUSTOM_FIELDS={} ZENDESK_CUSTOM_FIELDS={},
ENABLE_ENTERPRISE_INTEGRATION=False
) )
@mock.patch("util.views.dog_stats_api") @mock.patch("util.views.dog_stats_api")
@mock.patch("util.views._ZendeskApi", autospec=True) @mock.patch("util.views._ZendeskApi", autospec=True)
class SubmitFeedbackTest(TestCase): class SubmitFeedbackTest(EnterpriseServiceMockMixin, TestCase):
""" """
Class to test the submit_feedback function in views. Class to test the submit_feedback function in views.
""" """
...@@ -72,6 +80,13 @@ class SubmitFeedbackTest(TestCase): ...@@ -72,6 +80,13 @@ class SubmitFeedbackTest(TestCase):
# This does not contain issue_type nor course_id to ensure that they are optional # This does not contain issue_type nor course_id to ensure that they are optional
self._auth_fields = {"subject": "a subject", "details": "some details"} self._auth_fields = {"subject": "a subject", "details": "some details"}
# Create a service user, because the track selection page depends on it
UserFactory.create(
username='enterprise_worker',
email="enterprise_worker@example.com",
password="edx",
)
def _build_and_run_request(self, user, fields): def _build_and_run_request(self, user, fields):
""" """
Generate a request and invoke the view, returning the response. Generate a request and invoke the view, returning the response.
...@@ -87,6 +102,7 @@ class SubmitFeedbackTest(TestCase): ...@@ -87,6 +102,7 @@ class SubmitFeedbackTest(TestCase):
REMOTE_ADDR=TEST_REQUEST_HEADERS["REMOTE_ADDR"], REMOTE_ADDR=TEST_REQUEST_HEADERS["REMOTE_ADDR"],
SERVER_NAME=TEST_REQUEST_HEADERS["SERVER_NAME"], SERVER_NAME=TEST_REQUEST_HEADERS["SERVER_NAME"],
) )
req.site = SiteFactory.create()
req.user = user req.user = user
return views.submit_feedback(req) return views.submit_feedback(req)
...@@ -441,6 +457,69 @@ class SubmitFeedbackTest(TestCase): ...@@ -441,6 +457,69 @@ class SubmitFeedbackTest(TestCase):
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update) self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
self._assert_datadog_called(datadog_mock, datadog_tags) self._assert_datadog_called(datadog_mock, datadog_tags)
@httpretty.activate
@data(
("course-v1:testOrg+testCourseNumber+testCourseRun", True),
("course-v1:testOrg+testCourseNumber+testCourseRun", False),
)
@unpack
@override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG, ENABLE_ENTERPRISE_INTEGRATION=True)
def test_valid_request_auth_user_with_enterprise_info(self, course_id, enrolled, zendesk_mock_class, datadog_mock):
"""
Test a valid request from an authenticated user with enterprise tags.
"""
self.mock_enterprise_learner_api()
zendesk_mock_instance = zendesk_mock_class.return_value
user = self._auth_user
fields = self._auth_fields.copy()
if course_id is not None:
fields["course_id"] = course_id
ticket_id = 42
zendesk_mock_instance.create_ticket.return_value = ticket_id
zendesk_tags = ["enterprise_learner", "LMS"]
datadog_tags = ['learner_type:enterprise_learner']
zendesk_custom_fields = []
if course_id:
zendesk_tags.insert(0, course_id)
datadog_tags.insert(0, "course_id:{}".format(course_id))
zendesk_custom_fields.append({"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id})
if enrolled is not None:
enrollment = CourseEnrollmentFactory.create(
user=user,
course_id=course_id,
is_active=enrolled
)
if enrollment.is_active:
zendesk_custom_fields.append(
{"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enrollment_mode"], "value": enrollment.mode}
)
zendesk_custom_fields.append(
{
"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enterprise_customer_name"],
"value": 'TestShib'
}
)
ticket = self._build_zendesk_ticket(
recipient=TEST_SUPPORT_EMAIL,
name=user.profile.name,
email=user.email,
subject=fields["subject"],
details=fields["details"],
tags=zendesk_tags,
custom_fields=zendesk_custom_fields
)
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)
self._test_success(user, fields)
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
self._assert_datadog_called(datadog_mock, datadog_tags)
def test_get_request(self, zendesk_mock_class, datadog_mock): def test_get_request(self, zendesk_mock_class, datadog_mock):
"""Test that a GET results in a 405 even with all required fields""" """Test that a GET results in a 405 even with all required fields"""
req = self._request_factory.get("/submit_feedback", data=self._anon_fields) req = self._request_factory.get("/submit_feedback", data=self._anon_fields)
......
...@@ -23,6 +23,7 @@ from opaque_keys.edx.keys import CourseKey, UsageKey ...@@ -23,6 +23,7 @@ from opaque_keys.edx.keys import CourseKey, UsageKey
from edxmako.shortcuts import render_to_response, render_to_string from edxmako.shortcuts import render_to_response, render_to_string
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.features.enterprise_support import api as enterprise_api
import track.views import track.views
from student.roles import GlobalStaff from student.roles import GlobalStaff
from student.models import CourseEnrollment from student.models import CourseEnrollment
...@@ -223,7 +224,7 @@ class _ZendeskApi(object): ...@@ -223,7 +224,7 @@ class _ZendeskApi(object):
return None return None
def _get_zendesk_custom_field_context(request): def _get_zendesk_custom_field_context(request, **kwargs):
""" """
Construct a dictionary of data that can be stored in Zendesk custom fields. Construct a dictionary of data that can be stored in Zendesk custom fields.
""" """
...@@ -241,6 +242,11 @@ def _get_zendesk_custom_field_context(request): ...@@ -241,6 +242,11 @@ def _get_zendesk_custom_field_context(request):
if enrollment and enrollment.is_active: if enrollment and enrollment.is_active:
context["enrollment_mode"] = enrollment.mode context["enrollment_mode"] = enrollment.mode
enterprise_learner_data = kwargs.get('learner_data', None)
if enterprise_learner_data:
enterprise_customer_name = enterprise_learner_data[0]['enterprise_customer']['name']
context["enterprise_customer_name"] = enterprise_customer_name
return context return context
...@@ -434,6 +440,12 @@ def submit_feedback(request): ...@@ -434,6 +440,12 @@ def submit_feedback(request):
success = False success = False
context = get_feedback_form_context(request) context = get_feedback_form_context(request)
#Update the tag info with 'enterprise_learner' if the user belongs to an enterprise customer.
enterprise_learner_data = enterprise_api.get_enterprise_learner_data(site=request.site, user=request.user)
if enterprise_learner_data:
context["tags"]["learner_type"] = "enterprise_learner"
support_backend = configuration_helpers.get_value('CONTACT_FORM_SUBMISSION_BACKEND', SUPPORT_BACKEND_ZENDESK) support_backend = configuration_helpers.get_value('CONTACT_FORM_SUBMISSION_BACKEND', SUPPORT_BACKEND_ZENDESK)
if support_backend == SUPPORT_BACKEND_EMAIL: if support_backend == SUPPORT_BACKEND_EMAIL:
...@@ -456,7 +468,7 @@ def submit_feedback(request): ...@@ -456,7 +468,7 @@ def submit_feedback(request):
custom_fields = None custom_fields = None
if settings.ZENDESK_CUSTOM_FIELDS: if settings.ZENDESK_CUSTOM_FIELDS:
custom_field_context = _get_zendesk_custom_field_context(request) custom_field_context = _get_zendesk_custom_field_context(request, learner_data=enterprise_learner_data)
custom_fields = _format_zendesk_custom_fields(custom_field_context) custom_fields = _format_zendesk_custom_fields(custom_field_context)
success = _record_feedback_in_zendesk( success = _record_feedback_in_zendesk(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment