Skip to content

Commit

Permalink
feat: extend enterprise customer serializer to add detail for support…
Browse files Browse the repository at this point in the history
… tool (#2174)

* feat: extend enterprise customer serializer to add detail for support tool

* fix: lint error
  • Loading branch information
katrinan029 authored Jul 22, 2024
1 parent d7e67a8 commit 0fc9ad0
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ Unreleased
----------
* nothing unreleased

[4.21.7]
---------
* feat: extend enterprise customer serializer to add detail for support tool

[4.21.6]
---------
* feat: add waffle flag for enterprise customer support tool
Expand Down
2 changes: 1 addition & 1 deletion enterprise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
Your project description goes here.
"""

__version__ = "4.21.6"
__version__ = "4.21.7"
33 changes: 33 additions & 0 deletions enterprise/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from enterprise.utils import (
CourseEnrollmentDowngradeError,
CourseEnrollmentPermissionError,
get_active_sso_configurations_for_customer,
get_integrations_for_customers,
get_last_course_run_end_date,
has_course_run_available_for_enrollment,
Expand Down Expand Up @@ -341,6 +342,38 @@ def get_enterprise_notification_banner(self, obj):
return AdminNotificationSerializer(notification_queryset).data


class EnterpriseCustomerSupportToolSerializer(EnterpriseCustomerSerializer):
"""
Extends the EnterpriseCustomerSerializer with additional fields to needed in the
MFE Support tool.
"""
class Meta:
model = models.EnterpriseCustomer
fields = (
'uuid', 'name', 'slug', 'active', 'auth_org_id', 'site', 'enable_data_sharing_consent',
'enforce_data_sharing_consent', 'branding_configuration', 'disable_expiry_messaging_for_learner_credit',
'identity_provider', 'enable_audit_enrollment', 'replace_sensitive_sso_username',
'enable_portal_code_management_screen', 'sync_learner_profile_data', 'enable_audit_data_reporting',
'enable_learner_portal', 'enable_learner_portal_offers', 'enable_portal_learner_credit_management_screen',
'enable_executive_education_2U_fulfillment', 'enable_portal_reporting_config_screen',
'enable_portal_saml_configuration_screen', 'contact_email',
'enable_portal_subscription_management_screen', 'hide_course_original_price', 'enable_analytics_screen',
'enable_integrated_customer_learner_portal_search', 'enable_generation_of_api_credentials',
'enable_portal_lms_configurations_screen', 'sender_alias', 'identity_providers',
'enterprise_customer_catalogs', 'reply_to', 'enterprise_notification_banner', 'hide_labor_market_data',
'modified', 'enable_universal_link', 'enable_browse_and_request', 'admin_users',
'enable_learner_portal_sidebar_message', 'learner_portal_sidebar_content',
'enable_pathways', 'enable_programs', 'enable_demo_data_for_analytics_and_lpr', 'enable_academies',
'enable_one_academy', 'active_integrations', 'show_videos_in_learner_portal_search_results',
'default_language', 'country', 'enable_slug_login', 'active_sso_configurations'
)

active_sso_configurations = serializers.SerializerMethodField()

def get_active_sso_configurations(self, obj):
return get_active_sso_configurations_for_customer(obj.uuid)


class EnterpriseCustomerBasicSerializer(serializers.ModelSerializer):
"""
Serializer for EnterpriseCustomer model only for name and id fields.
Expand Down
18 changes: 18 additions & 0 deletions enterprise/api/v1/views/enterprise_customer.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ def get_permissions(self):
def get_serializer_class(self):
if self.action == 'basic_list':
return serializers.EnterpriseCustomerBasicSerializer
if self.action == 'support_tool':
return serializers.EnterpriseCustomerSupportToolSerializer
return self.serializer_class

@action(detail=False)
Expand All @@ -113,6 +115,22 @@ def basic_list(self, request, *arg, **kwargs):
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

@action(detail=False)
# pylint: disable=unused-argument
def support_tool(self, request, *arg, **kwargs):
"""
Enterprise Customer's detail data for the support tool
Supported query param:
- uuid: filter the enterprise customer uuid .
"""
enterprise_uuid = request.GET.get('uuid')
queryset = self.get_queryset().order_by('name')
if enterprise_uuid:
queryset = queryset.filter(uuid=enterprise_uuid)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)

@method_decorator(has_permission_or_group('enterprise.can_access_admin_dashboard', PROVISIONING_ADMINS_GROUP))
def create(self, request, *args, **kwargs):
"""
Expand Down
45 changes: 41 additions & 4 deletions enterprise/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,13 @@ def enterprise_customer_model():
return apps.get_model('enterprise', 'EnterpriseCustomer')


def enterprise_customer_sso_configuration_model():
"""
Returns the ``EnterpriseCustomerSsoConfiguration`` class.
"""
return apps.get_model('enterprise', 'EnterpriseCustomerSsoConfiguration')


def enterprise_enrollment_source_model():
"""
Returns the ``EnterpriseEnrollmentSource`` class.
Expand Down Expand Up @@ -2459,16 +2466,46 @@ def get_integrated_channel_choices():

def get_integrations_for_customers(customer_uuid):
"""
Helper method to return channel code for each enterprise customer with active integrations.
Helper method to return active integrations code for each enterprise customer.
Arguments:
customer_uuid (UUI): uuid of an enterprise customer
Returns:
list: a list of integration channel codes.
list: a list of integrations.
"""
unique_integrations = []
integrated_channel_choices = get_integrated_channel_choices()
for code, choice in integrated_channel_choices.items():
if choice.objects.filter(enterprise_customer__uuid=customer_uuid, active=True):
unique_integrations.append(code)
integration = choice.objects.filter(enterprise_customer__uuid=customer_uuid, active=True).values().first()
if integration is not None:
unique_integrations.append({
'channel_code': code,
'created': datetime.datetime.strftime(integration.get('created'), '%B %d, %Y'),
'modified': datetime.datetime.strftime(integration.get('modified'), '%B %d, %Y'),
'display_name': integration.get('display_name'),
'active': integration.get('active'),
})
return unique_integrations


def get_active_sso_configurations_for_customer(customer_uuid):
"""
Helper method to get active sso configurations for each enterprise customer
Arguments:
customer_uuid (UUID): uuid of an enterprise customer
Returns:
list: a list of active sso configurations
"""
SsoConfigurations = enterprise_customer_sso_configuration_model()
sso_configurations = SsoConfigurations.objects.filter(enterprise_customer__uuid=customer_uuid,
active=True).values()
active_configurations = []
if sso_configurations:
for sso_configuration in sso_configurations:
active_configurations.append({
'created': datetime.datetime.strftime(sso_configuration.get('created'), '%B %d, %Y'),
'modified': datetime.datetime.strftime(sso_configuration.get('modified'), '%B %d, %Y'),
'active': sso_configuration.get('active'),
'display_name': sso_configuration.get('display_name'),
})
return active_configurations
106 changes: 105 additions & 1 deletion tests/test_enterprise/api/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@
kwargs={'pk': FAKE_UUIDS[0]}
)
ENTERPRISE_CUSTOMER_BASIC_LIST_ENDPOINT = reverse('enterprise-customer-basic-list')
ENTERPRISE_CUSTOMER_SUPPORT_TOOL_ENDPOINT = reverse('enterprise-customer-support-tool')
ENTERPRISE_CUSTOMER_CONTAINS_CONTENT_ENDPOINT = reverse(
'enterprise-customer-contains-content-items',
kwargs={'pk': FAKE_UUIDS[0]}
Expand Down Expand Up @@ -1786,7 +1787,13 @@ class TestEnterpriseCustomerViewSet(BaseTestEnterpriseAPIViews):
'enable_demo_data_for_analytics_and_lpr': False,
'enable_academies': False,
'enable_one_academy': False,
'active_integrations': ['BLACKBOARD'],
'active_integrations': [{
'channel_code': 'BLACKBOARD',
'created': datetime.strftime(datetime.now(), '%B %d, %Y'),
'modified': datetime.strftime(datetime.now(), '%B %d, %Y'),
'display_name': 'BLACKBOARD 1',
'active': True,
}],
'show_videos_in_learner_portal_search_results': False,
'default_language': 'en',
'country': 'US',
Expand Down Expand Up @@ -1843,6 +1850,103 @@ def test_enterprise_customer_basic_list(self):
response = self.client.get(url, {'name_or_uuid': name_or_uuid})
assert name_or_uuid_enterprise_customers == self.load_json(response.content)

@ddt.data(
(
factories.EnterpriseCustomerSsoConfigurationFactory,
ENTERPRISE_CUSTOMER_SUPPORT_TOOL_ENDPOINT,
itemgetter('uuid'),
[{
'active': True,
'display_name': 'Test SSO',
'enterprise_customer__uuid': FAKE_UUIDS[0],
'enterprise_customer__name': 'Test Enterprise Customer',
'enterprise_customer__slug': TEST_SLUG,
'enterprise_customer__active': True,
'enterprise_customer__auth_org_id': 'asdf3e2wdas',
'enterprise_customer__enable_data_sharing_consent': True,
'enterprise_customer__enforce_data_sharing_consent': 'at_enrollment',
'enterprise_customer__enable_audit_data_reporting': True,
'enterprise_customer__contact_email': '[email protected]',
'enterprise_customer__sender_alias': 'Test Sender Alias',
'enterprise_customer__reply_to': '[email protected]',
'enterprise_customer__hide_labor_market_data': False,
'enterprise_customer__modified': '2021-10-20T19:01:31Z',
'enterprise_customer__site__domain': 'example.com',
'enterprise_customer__site__name': 'example.com',
}],
[{
'uuid': FAKE_UUIDS[0], 'name': 'Test Enterprise Customer',
'slug': TEST_SLUG, 'active': True,
'auth_org_id': 'asdf3e2wdas',
'site': {
'domain': 'example.com', 'name': 'example.com'
},
'enable_data_sharing_consent': True,
'enforce_data_sharing_consent': 'at_enrollment',
'branding_configuration': get_default_branding_object(FAKE_UUIDS[0], TEST_SLUG),
'identity_provider': None,
'enable_audit_enrollment': False,
'replace_sensitive_sso_username': False, 'enable_portal_code_management_screen': False,
'sync_learner_profile_data': False,
'disable_expiry_messaging_for_learner_credit': False,
'enable_audit_data_reporting': True,
'enable_learner_portal': True,
'enable_learner_portal_offers': False,
'enable_portal_learner_credit_management_screen': False,
'enable_executive_education_2U_fulfillment': False,
'enable_portal_reporting_config_screen': False,
'enable_portal_saml_configuration_screen': False,
'contact_email': '[email protected]',
'enable_portal_subscription_management_screen': False,
'hide_course_original_price': False,
'enable_analytics_screen': True,
'enable_integrated_customer_learner_portal_search': True,
'enable_learner_portal_sidebar_message': False,
'enable_portal_lms_configurations_screen': False,
'sender_alias': 'Test Sender Alias',
'identity_providers': [],
'enterprise_customer_catalogs': [],
'reply_to': '[email protected]',
'enterprise_notification_banner': {'title': '', 'text': ''},
'hide_labor_market_data': False,
'modified': '2021-10-20T19:01:31Z',
'enable_universal_link': False,
'enable_browse_and_request': False,
'admin_users': [],
'enable_generation_of_api_credentials': False,
'learner_portal_sidebar_content': 'Test message',
'enable_pathways': True,
'enable_programs': True,
'enable_demo_data_for_analytics_and_lpr': False,
'enable_academies': False,
'enable_one_academy': False,
'active_integrations': [],
'show_videos_in_learner_portal_search_results': False,
'default_language': 'en',
'country': 'US',
'enable_slug_login': False,
'active_sso_configurations': [{
'created': datetime.strftime(datetime.now(), '%B %d, %Y'),
'display_name': 'Test SSO',
'modified': datetime.strftime(datetime.now(), '%B %d, %Y'),
'active': True,
}],
}],
),
)
@ddt.unpack
@mock.patch('enterprise.utils.get_logo_url')
def test_enterprise_customer_support_tool(
self, factory, url, sorting_key, model_items, expected_json, mock_get_logo_url):
"""
Test support tool endpoint of enterprise_customers
"""
mock_get_logo_url.return_value = 'http://fake.url'
self.create_items(factory, model_items)
response = self.client.get(settings.TEST_SERVER + url)
response = self.load_json(response.content)
assert sorted(expected_json, key=sorting_key) == sorted(response, key=sorting_key)

@ddt.data(
# Request missing required permissions query param.
(True, False, [], {}, False, {'detail': 'User is not allowed to access the view.'}, False, False, False, False),
Expand Down

0 comments on commit 0fc9ad0

Please sign in to comment.