Skip to content

Commit

Permalink
Merge pull request #565 from edx/bexline/move_to_completed
Browse files Browse the repository at this point in the history
ENT-2230 Add patch method on learner portal enrollment endpoint
  • Loading branch information
brittneyexline authored Sep 6, 2019
2 parents 6e48f53 + 736a300 commit 69cdb2a
Show file tree
Hide file tree
Showing 8 changed files with 257 additions and 40 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ Change Log
Unreleased
----------

[1.9.12] - 2019-09-06
---------------------

* Implement "move to completed" functionality for Enterprise Enrollments.

[1.9.11] - 2019-09-05
---------------------

Expand Down
2 changes: 1 addition & 1 deletion enterprise/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

from __future__ import absolute_import, unicode_literals

__version__ = "1.9.11"
__version__ = "1.9.12"

default_app_config = "enterprise.apps.EnterpriseConfig" # pylint: disable=invalid-name
37 changes: 26 additions & 11 deletions enterprise_learner_portal/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,28 +43,43 @@ def to_representation(self, instance):
representation = super(EnterpriseCourseEnrollmentSerializer, self).to_representation(instance)

request = self.context['request']
course_run_id = instance.course_id
user = request.user

# Course Overview
course_overview = self._get_course_overview(course_run_id)

# Certificate
certificate_info = get_certificate_for_user(user.username, instance['id']) or {}
certificate_info = get_certificate_for_user(user.username, course_run_id) or {}
representation['certificate_download_url'] = certificate_info.get('download_url')

# Email enabled
emails_enabled = get_emails_enabled(user, instance['id'])
emails_enabled = get_emails_enabled(user, course_run_id)
if emails_enabled is not None:
representation['emails_enabled'] = emails_enabled

representation['course_run_id'] = instance['id']
representation['course_run_id'] = course_run_id
representation['course_run_status'] = get_course_run_status(
instance,
course_overview,
certificate_info,
instance
)
representation['start_date'] = instance['start']
representation['end_date'] = instance['end']
representation['display_name'] = instance['display_name_with_default']
representation['course_run_url'] = get_course_run_url(request, instance['id'])
representation['due_dates'] = get_due_dates(request, instance['id'], user)
representation['pacing'] = instance['pacing']
representation['org_name'] = instance['display_org_with_default']
representation['start_date'] = course_overview['start']
representation['end_date'] = course_overview['end']
representation['display_name'] = course_overview['display_name_with_default']
representation['course_run_url'] = get_course_run_url(request, course_run_id)
representation['due_dates'] = get_due_dates(request, course_run_id, user)
representation['pacing'] = course_overview['pacing']
representation['org_name'] = course_overview['display_org_with_default']

return representation

def _get_course_overview(self, course_run_id):
"""
Get the appropriate course overview from the context.
"""
for overview in self.context['course_overviews']:
if overview['id'] == course_run_id:
return overview

return None
53 changes: 48 additions & 5 deletions enterprise_learner_portal/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,59 @@ def get(self, request):
user_id=user.id,
enterprise_customer__uuid=enterprise_customer_id,
)
course_ids_for_ent_enrollments = EnterpriseCourseEnrollment.objects.filter(
enterprise_enrollments = EnterpriseCourseEnrollment.objects.filter(
enterprise_customer_user=enterprise_customer_user
).values_list('course_id', flat=True)
)

overviews = get_course_overviews(course_ids_for_ent_enrollments)
course_overviews = get_course_overviews(enterprise_enrollments.values_list('course_id', flat=True))

data = EnterpriseCourseEnrollmentSerializer(
overviews,
enterprise_enrollments,
many=True,
context={'request': request},
context={'request': request, 'course_overviews': course_overviews},
).data

return Response(data)

def patch(self, request):
"""
Patch method for the view.
"""
if get_course_overviews is None:
raise NotConnectedToOpenEdX(
_('To use this endpoint, this package must be '
'installed in an Open edX environment.')
)

user = request.user
enterprise_customer_id = request.query_params.get('enterprise_id', None)
course_id = request.query_params.get('course_id', None)
marked_done = request.query_params.get('marked_done', None)
if not enterprise_customer_id or not course_id or marked_done is None:
return Response(
{'error': 'enterprise_id, course_id, and marked_done must be provided as query parameters'},
status=HTTP_400_BAD_REQUEST
)

enterprise_customer_user = get_object_or_404(
EnterpriseCustomerUser,
user_id=user.id,
enterprise_customer__uuid=enterprise_customer_id,
)

enterprise_enrollment = get_object_or_404(
EnterpriseCourseEnrollment,
enterprise_customer_user=enterprise_customer_user,
course_id=course_id
)

enterprise_enrollment.marked_done = marked_done
enterprise_enrollment.save()

course_overviews = get_course_overviews([course_id])
data = EnterpriseCourseEnrollmentSerializer(
enterprise_enrollment,
context={'request': request, 'course_overviews': course_overviews},
).data

return Response(data)
6 changes: 4 additions & 2 deletions enterprise_learner_portal/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class CourseRunProgressStatuses(object):
COMPLETED = 'completed'


def get_course_run_status(course_overview, certificate_info):
def get_course_run_status(course_overview, certificate_info, enterprise_enrollment):
"""
Get the progress status of a course run, given the state of a user's certificate in the course.
Expand All @@ -43,7 +43,9 @@ def get_course_run_status(course_overview, certificate_info):
is_certificate_passing = certificate_info.get('is_passing', False)
certificate_creation_date = certificate_info.get('created', datetime.max)

if course_overview['pacing'] == 'instructor':
if enterprise_enrollment and enterprise_enrollment.marked_done:
return CourseRunProgressStatuses.COMPLETED
elif course_overview['pacing'] == 'instructor':
if course_overview['has_ended']:
return CourseRunProgressStatuses.COMPLETED
elif course_overview['has_started']:
Expand Down
31 changes: 19 additions & 12 deletions tests/test_enterprise_learner_portal/api/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def setUp(self):

self.user = factories.UserFactory.create(is_staff=True, is_active=True)
self.factory = RequestFactory()
self.enterprise_customer_user = factories.EnterpriseCustomerUserFactory.create(user_id=self.user.id)

@mock.patch('enterprise_learner_portal.api.v1.serializers.get_course_run_status')
@mock.patch('enterprise_learner_portal.api.v1.serializers.get_emails_enabled')
Expand All @@ -44,8 +45,18 @@ def test_serializer_representation(
):
"""
EnterpriseCourseEnrollmentSerializer should create proper representation
based on the instance data it receives (a course_overview)
based on the instance data it receives (an enterprise course enrollment)
"""
course_run_id = 'some+id+here'
course_overviews = [{
'id': course_run_id,
'start': 'a datetime object',
'end': 'a datetime object',
'display_name_with_default': 'a default name',
'pacing': 'instructor',
'display_org_with_default': 'my university',
}]

mock_get_cert.return_value = {
'download_url': 'example.com',
'is_passing': True,
Expand All @@ -56,28 +67,24 @@ def test_serializer_representation(
mock_get_emails_enabled.return_value = True
mock_get_course_run_status.return_value = 'completed'

input_data = {
'id': 'some+id+here',
'start': 'a datetime object',
'end': 'a datetime object',
'display_name_with_default': 'a default name',
'pacing': 'instructor',
'display_org_with_default': 'my university',
}
enterprise_enrollment = factories.EnterpriseCourseEnrollmentFactory.create(
enterprise_customer_user=self.enterprise_customer_user,
course_id=course_run_id
)

request = self.factory.get('/')
request.user = self.user

serializer = EnterpriseCourseEnrollmentSerializer(
[input_data],
[enterprise_enrollment],
many=True,
context={'request': request},
context={'request': request, 'course_overviews': course_overviews},
)

expected = OrderedDict([
('certificate_download_url', 'example.com'),
('emails_enabled', True),
('course_run_id', 'some+id+here'),
('course_run_id', course_run_id),
('course_run_status', 'completed'),
('start_date', 'a datetime object'),
('end_date', 'a datetime object'),
Expand Down
Loading

0 comments on commit 69cdb2a

Please sign in to comment.