Skip to content
This repository has been archived by the owner on Feb 27, 2024. It is now read-only.

Commit

Permalink
MCKIN-21885: add filter to remove course count (#60)
Browse files Browse the repository at this point in the history
* remove course count test

* add course count exclusion filter on list api

* fix tests
  • Loading branch information
msaqib52 authored Aug 4, 2020
1 parent 39e3035 commit 780de67
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 37 deletions.
11 changes: 11 additions & 0 deletions edx_solutions_organizations/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ class Meta(object):
'contact_phone', 'logo_url', 'created', 'modified', 'number_of_participants')


class OrganizationWithParticipantCountSerializer(BasicOrganizationSerializer):
""" Serializer for Organization fields with number of participants """
number_of_participants = serializers.IntegerField()

class Meta(object):
""" Serializer/field specification """
model = Organization
fields = ('url', 'id', 'name', 'display_name', 'contact_name', 'contact_email',
'contact_phone', 'logo_url', 'created', 'modified', 'number_of_participants')


class OrganizationAttributesSerializer(serializers.ModelSerializer):
""" Serializer for Organization Attributes interactions """

Expand Down
86 changes: 50 additions & 36 deletions edx_solutions_organizations/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@
from edx_solutions_organizations.serializers import OrganizationAttributesSerializer
from edx_solutions_organizations.utils import generate_key_for_field, is_key_exists, is_label_exists, \
generate_random_key_for_field
from .serializers import OrganizationSerializer, BasicOrganizationSerializer, OrganizationWithCourseCountSerializer
from .serializers import (
OrganizationSerializer,
BasicOrganizationSerializer,
OrganizationWithCourseCountSerializer,
OrganizationWithParticipantCountSerializer,
)
from .models import Organization, OrganizationGroupUser


Expand All @@ -59,6 +64,7 @@ def list(self, request, *args, **kwargs):
queryset = self.get_queryset()

exclude_type = request.query_params.get('type', None)
include_course_counts = request.query_params.get('include_course_counts', 'true')
ids = request.query_params.get('ids', None)
if ids:
ids = [int(id) for id in ids.split(',')]
Expand All @@ -68,44 +74,52 @@ def list(self, request, *args, **kwargs):
if display_name is not None:
queryset = queryset.filter(display_name=display_name)

if exclude_type:

# Filtering company admin users to exclude
admin_users = User.objects.filter(id__in=list(queryset.filter(
Q(users__groups__groupprofile__name=exclude_type)
).distinct().values_list('users', flat=True)))

admin_users_dict = {}
for user in admin_users:
other_companies = list(user.organizations.all())[1:]
for company in other_companies:
admin_users_dict.setdefault(company.id, []).append(user.id)

# list of users with corresponding organizations to exclude
exclude_admin_users = [
Q(id=org_id) & Q(users__courseenrollment__user_id__in=users) for
org_id, users in admin_users_dict.items()]
if exclude_admin_users:
exclude_admin_users = reduce(lambda a, b: a | b, exclude_admin_users)
q_object = ~Q(exclude_admin_users)
if str2bool(include_course_counts):
if exclude_type:
q_object = Q()

# Filtering roles to exclude
roles_to_exclude = [CourseInstructorRole.ROLE, CourseStaffRole.ROLE, CourseObserverRole.ROLE, CourseAssistantRole.ROLE]
user_ids = CourseAccessRole.objects.filter(role__in=roles_to_exclude).distinct().values_list('user_id', flat=True)
q_object.add(~Q(users__courseenrollment__user_id__in=user_ids), Q.AND)

# Filtering company admin users to exclude
admin_users = User.objects.filter(id__in=list(queryset.filter(
Q(users__groups__groupprofile__name=exclude_type)
).distinct().values_list('users', flat=True)))

admin_users_dict = {}
for user in admin_users:
other_companies = list(user.organizations.all())[1:]
for company in other_companies:
admin_users_dict.setdefault(company.id, []).append(user.id)

# list of users with corresponding organizations to exclude
exclude_admin_users = [
Q(id=org_id) & Q(users__courseenrollment__user_id__in=users) for
org_id, users in admin_users_dict.items()]
if exclude_admin_users:
exclude_admin_users = reduce(lambda a, b: a | b, exclude_admin_users)
q_object.add(~Q(exclude_admin_users), Q.AND)

# filter only users courses that are enrolled i.e is_active=True.
q_object.add(Q(users__courseenrollment__is_active=True), Q.AND)

# annotating queryset to get number of courses
queryset = queryset.annotate(
number_of_courses=Count(
Case(
When(q_object, then=F('users__courseenrollment__course_id'))
), distinct=True
)
)
else:
q_object = True

# filter only users courses that are enrolled i.e is_active=True.
q_object.add(Q(users__courseenrollment__is_active=True), Q.AND)

# annotating queryset to get number of courses
queryset = queryset.annotate(
number_of_courses=Count(
Case(
When(q_object, then=F('users__courseenrollment__course_id'))
), distinct=True
queryset = queryset.annotate(
number_of_courses=Count('users__courseenrollment__course_id', distinct=True)
)
)
else:
queryset = queryset.annotate(
number_of_courses=Count('users__courseenrollment__course_id', distinct=True)
)
self.serializer_class = OrganizationWithParticipantCountSerializer

self.queryset = queryset.annotate(
number_of_participants=Count('users', distinct=True)
)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

setup(
name='organizations-edx-platform-extensions',
version='2.0.4',
version='2.0.5',
description='Organization management extension for edX platform',
long_description=open('README.rst').read(),
author='edX',
Expand Down

0 comments on commit 780de67

Please sign in to comment.