Skip to content

Commit

Permalink
feat: adds sorting support to enterprise-customer-members endpoint (#…
Browse files Browse the repository at this point in the history
…2311)

* feat: adds sorting support to enterprise-customer-members endpoint
  • Loading branch information
katrinan029 authored Jan 13, 2025
1 parent fd8c1c5 commit 23d0122
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 4 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

[5.6.0]
--------
* feat: Adds sorting support to enterprise-customer-members endpoint

[5.5.2]
--------
* feat: Add page_size support to enterprise-customer-members endpoint
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__ = "5.5.2"
__version__ = "5.6.0"
18 changes: 17 additions & 1 deletion enterprise/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1922,7 +1922,22 @@ def get_role_assignments(self, obj):
return None


class EnterpriseMembersSerializer(serializers.Serializer):
class EnterpriseCustomerMembersRequestQuerySerializer(serializers.Serializer):
"""
Serializer for the Enterprise Customer Members endpoint query filter
"""
user_query = serializers.CharField(required=False, max_length=250)
sort_by = serializers.ChoiceField(
choices=[
('name', 'name'),
('joined_org', 'joined_org'),
],
required=False,
)
is_reversed = serializers.BooleanField(required=False, default=False)


class EnterpriseMembersSerializer(serializers.ModelSerializer):
"""
Serializer for EnterpriseCustomerUser model with additions.
"""
Expand Down Expand Up @@ -1954,6 +1969,7 @@ def get_enterprise_customer_user(self, obj):
"""
if user := obj:
return {
"user_id": user[0],
"email": user[1],
"joined_org": user[2].strftime("%b %d, %Y"),
"name": user[3],
Expand Down
31 changes: 29 additions & 2 deletions enterprise/api/v1/views/enterprise_customer_members.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from rest_framework import permissions, response, status
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

from django.core.exceptions import ValidationError
from django.db import connection
Expand Down Expand Up @@ -63,13 +64,31 @@ class EnterpriseCustomerMembersViewSet(EnterpriseReadOnlyModelViewSet):
def get_members(self, request, *args, **kwargs):
"""
Get all members associated with that enterprise customer
Request Arguments:
- ``enterprise_uuid`` (URL location, required): The uuid of the enterprise from which learners should be listed.
Optional query params:
- ``user_query`` (string, optional): Filter the returned members by user name and email with a provided
sub-string
- ``sort_by`` (string, optional): Specify how the returned members should be ordered. Supported sorting values
are `joined_org`, `name`, and `enrollments`.
- ``is_reversed`` (bool, optional): Include to reverse the records in descending order. By default, the results
returned are in ascending order.
"""
query_params = self.request.query_params
param_serializers = serializers.EnterpriseCustomerMembersRequestQuerySerializer(
data=query_params
)
if not param_serializers.is_valid():
return Response(param_serializers.errors, status=400)
enterprise_uuid = kwargs.get("enterprise_uuid", None)
# Raw sql is picky about uuid format
uuid_no_dashes = str(enterprise_uuid).replace("-", "")
users = []
user_query = self.request.query_params.get("user_query", None)

user_query = param_serializers.validated_data.get('user_query')
is_reversed = param_serializers.validated_data.get('is_reversed', False)
sort_by = param_serializers.validated_data.get('sort_by')
# On logistration, the name field of auth_userprofile is populated, but if it's not
# filled in, we check the auth_user model for it's first/last name fields
# https://2u-internal.atlassian.net/wiki/spaces/ENGAGE/pages/747143186/Use+of+full+name+in+edX#Data-on-Name-Field
Expand Down Expand Up @@ -109,6 +128,14 @@ def get_members(self, request, *args, **kwargs):
status=status.HTTP_404_NOT_FOUND,
)

if sort_by:
lambda_keys = {
# 3 and 2 are indices in the tuple associated to a user row (uuid, email, joined_org, name)
'name': lambda t: t[3],
'joined_org': lambda t: t[2],
}
users = sorted(users, key=lambda_keys.get(sort_by), reverse=is_reversed)

# paginate the queryset
users_page = self.paginator.paginate_queryset(users, request, view=self)

Expand Down
2 changes: 2 additions & 0 deletions tests/test_enterprise/api/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ def setUp(self):
def test_serialize_users(self):
expected_user = {
'enterprise_customer_user': {
'user_id': self.user_1.id,
'email': self.user_1.email,
'joined_org': self.user_1.date_joined.strftime("%b %d, %Y"),
'name': (self.user_1.first_name + ' ' + self.user_1.last_name),
Expand All @@ -609,6 +610,7 @@ def test_serialize_users(self):

expected_user_2 = {
'enterprise_customer_user': {
'user_id': self.user_2.id,
'email': self.user_2.email,
'joined_org': self.user_2.date_joined.strftime("%b %d, %Y"),
'name': self.user_2.first_name + ' ' + self.user_2.last_name,
Expand Down

0 comments on commit 23d0122

Please sign in to comment.