Add credit modein support enrollment tool.
Currently, enrollment support tool is only allowing support members to change course enrollment only one of the two modes i.e. audit and verified.To move a learner other than these modes,they need to ping devops.To broaden the scope of enrollment support tool,changes have been done so that enrollment would be changed to other modes as well. PROD-305
This commit is contained in:
@@ -333,7 +333,9 @@ class CourseMode(models.Model):
|
||||
|
||||
@classmethod
|
||||
@request_cached(CACHE_NAMESPACE)
|
||||
def modes_for_course(cls, course_id=None, include_expired=False, only_selectable=True, course=None):
|
||||
def modes_for_course(
|
||||
cls, course_id=None, include_expired=False, only_selectable=True, course=None, exclude_credit=True
|
||||
):
|
||||
"""
|
||||
Returns a list of the non-expired modes for a given course id
|
||||
|
||||
@@ -384,7 +386,7 @@ class CourseMode(models.Model):
|
||||
if only_selectable:
|
||||
if course is not None and hasattr(course, 'selectable_modes'):
|
||||
found_course_modes = course.selectable_modes
|
||||
else:
|
||||
elif exclude_credit:
|
||||
found_course_modes = found_course_modes.exclude(mode_slug__in=cls.CREDIT_MODES)
|
||||
|
||||
modes = ([mode.to_tuple() for mode in found_course_modes])
|
||||
|
||||
@@ -15,13 +15,14 @@ import six
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models import signals
|
||||
from django.urls import reverse
|
||||
from mock import patch
|
||||
from pytz import UTC
|
||||
|
||||
from common.test.utils import disable_signal
|
||||
from course_modes.models import CourseMode
|
||||
from course_modes.tests.factories import CourseModeFactory
|
||||
from lms.djangoapps.verify_student.models import VerificationDeadline
|
||||
from student.models import ENROLLED_TO_ENROLLED, CourseEnrollment, ManualEnrollmentAudit
|
||||
from student.models import ENROLLED_TO_ENROLLED, CourseEnrollment, CourseEnrollmentAttribute, ManualEnrollmentAudit
|
||||
from student.roles import GlobalStaff, SupportStaffRole
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase, SharedModuleStoreTestCase
|
||||
@@ -257,7 +258,8 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
|
||||
}, data[0])
|
||||
self.assertEqual(
|
||||
{CourseMode.VERIFIED, CourseMode.AUDIT, CourseMode.HONOR,
|
||||
CourseMode.NO_ID_PROFESSIONAL_MODE, CourseMode.PROFESSIONAL},
|
||||
CourseMode.NO_ID_PROFESSIONAL_MODE, CourseMode.PROFESSIONAL,
|
||||
CourseMode.CREDIT_MODE},
|
||||
{mode['slug'] for mode in data[0]['course_modes']}
|
||||
)
|
||||
|
||||
@@ -329,10 +331,9 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
|
||||
self.assertIsNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
|
||||
|
||||
@disable_signal(signals, 'post_save')
|
||||
@ddt.data('honor', 'audit', 'verified', 'professional', 'no-id-professional')
|
||||
@ddt.data('honor', 'audit', 'verified', 'professional', 'no-id-professional', 'credit')
|
||||
def test_update_enrollment_for_all_modes(self, new_mode):
|
||||
""" Verify support can changed the enrollment to all available modes
|
||||
except credit. """
|
||||
""" Verify support can changed the enrollment to all available modes"""
|
||||
self.assert_update_enrollment('username', new_mode)
|
||||
|
||||
@disable_signal(signals, 'post_save')
|
||||
@@ -342,10 +343,6 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
|
||||
self.set_course_end_date_and_expiry()
|
||||
self.assert_update_enrollment('username', new_mode)
|
||||
|
||||
def test_update_enrollment_with_credit_mode_throws_error(self):
|
||||
""" Verify that enrollment cannot be changed to credit mode. """
|
||||
self.assert_update_enrollment('username', CourseMode.CREDIT_MODE)
|
||||
|
||||
@ddt.data('username', 'email')
|
||||
def test_get_enrollments_with_expired_mode(self, search_string_type):
|
||||
""" Verify that page can get the all modes with archived course. """
|
||||
@@ -367,7 +364,7 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
|
||||
|
||||
def _assert_generated_modes(self, response):
|
||||
"""Dry method to generate course modes dict and test with response data."""
|
||||
modes = CourseMode.modes_for_course(self.course.id, include_expired=True)
|
||||
modes = CourseMode.modes_for_course(self.course.id, include_expired=True, exclude_credit=False)
|
||||
modes_data = []
|
||||
for mode in modes:
|
||||
expiry = mode.expiration_datetime.strftime('%Y-%m-%dT%H:%M:%SZ') if mode.expiration_datetime else None
|
||||
@@ -394,7 +391,7 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
|
||||
|
||||
self.assertEqual(
|
||||
{CourseMode.VERIFIED, CourseMode.AUDIT, CourseMode.NO_ID_PROFESSIONAL_MODE,
|
||||
CourseMode.PROFESSIONAL, CourseMode.HONOR},
|
||||
CourseMode.PROFESSIONAL, CourseMode.HONOR, CourseMode.CREDIT_MODE},
|
||||
{mode['slug'] for mode in data[0]['course_modes']}
|
||||
)
|
||||
|
||||
@@ -405,19 +402,25 @@ class SupportViewEnrollmentsTests(SharedModuleStoreTestCase, SupportViewTestCase
|
||||
'support:enrollment_list',
|
||||
kwargs={'username_or_email': getattr(self.student, search_string_type)}
|
||||
)
|
||||
response = self.client.post(url, data={
|
||||
'course_id': six.text_type(self.course.id),
|
||||
'old_mode': CourseMode.AUDIT,
|
||||
'new_mode': new_mode,
|
||||
'reason': 'Financial Assistance'
|
||||
})
|
||||
# Enrollment cannot be changed to credit mode.
|
||||
if new_mode == CourseMode.CREDIT_MODE:
|
||||
self.assertEqual(response.status_code, 400)
|
||||
else:
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIsNotNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
|
||||
self.assert_enrollment(new_mode)
|
||||
|
||||
with patch('support.views.enrollments.get_credit_provider_attribute_values') as mock_method:
|
||||
credit_provider = (
|
||||
[u'Arizona State University'], 'You are now eligible for credit from Arizona State University'
|
||||
)
|
||||
mock_method.return_value = credit_provider
|
||||
response = self.client.post(url, data={
|
||||
'course_id': six.text_type(self.course.id),
|
||||
'old_mode': CourseMode.AUDIT,
|
||||
'new_mode': new_mode,
|
||||
'reason': 'Financial Assistance'
|
||||
})
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertIsNotNone(ManualEnrollmentAudit.get_manual_enrollment_by_email(self.student.email))
|
||||
self.assert_enrollment(new_mode)
|
||||
if new_mode == 'credit':
|
||||
enrollment_attr = CourseEnrollmentAttribute.objects.first()
|
||||
self.assertEqual(enrollment_attr.value, unicode(credit_provider[0]))
|
||||
|
||||
def set_course_end_date_and_expiry(self):
|
||||
""" Set the course-end date and expire its verified mode."""
|
||||
|
||||
@@ -21,10 +21,11 @@ from edxmako.shortcuts import render_to_response
|
||||
from lms.djangoapps.support.decorators import require_support_permission
|
||||
from lms.djangoapps.support.serializers import ManualEnrollmentSerializer
|
||||
from lms.djangoapps.verify_student.models import VerificationDeadline
|
||||
from openedx.core.djangoapps.credit.email_utils import get_credit_provider_attribute_values
|
||||
from openedx.core.djangoapps.enrollments.api import get_enrollments, update_enrollment
|
||||
from openedx.core.djangoapps.enrollments.errors import CourseModeNotFoundError
|
||||
from openedx.core.djangoapps.enrollments.serializers import ModeSerializer
|
||||
from student.models import ENROLLED_TO_ENROLLED, CourseEnrollment, ManualEnrollmentAudit
|
||||
from student.models import ENROLLED_TO_ENROLLED, CourseEnrollment, CourseEnrollmentAttribute, ManualEnrollmentAudit
|
||||
from util.json_request import JsonResponse
|
||||
|
||||
|
||||
@@ -94,8 +95,6 @@ class EnrollmentSupportListView(GenericAPIView):
|
||||
username=user.username,
|
||||
old_mode=old_mode
|
||||
))
|
||||
if new_mode == CourseMode.CREDIT_MODE:
|
||||
return HttpResponseBadRequest(u'Enrollment cannot be changed to credit mode.')
|
||||
except KeyError as err:
|
||||
return HttpResponseBadRequest(u'The field {} is required.'.format(text_type(err)))
|
||||
except InvalidKeyError:
|
||||
@@ -119,6 +118,16 @@ class EnrollmentSupportListView(GenericAPIView):
|
||||
reason=reason,
|
||||
enrollment=enrollment
|
||||
)
|
||||
if new_mode == CourseMode.CREDIT_MODE:
|
||||
provider_ids = get_credit_provider_attribute_values(course_key, 'id')
|
||||
credit_provider_attr = {
|
||||
'namespace': 'credit',
|
||||
'name': 'provider_id',
|
||||
'value': provider_ids[0],
|
||||
}
|
||||
CourseEnrollmentAttribute.add_enrollment_attr(
|
||||
enrollment=enrollment, data_list=[credit_provider_attr]
|
||||
)
|
||||
return JsonResponse(ManualEnrollmentSerializer(instance=manual_enrollment).data)
|
||||
except CourseModeNotFoundError as err:
|
||||
return HttpResponseBadRequest(text_type(err))
|
||||
@@ -178,7 +187,8 @@ class EnrollmentSupportListView(GenericAPIView):
|
||||
"""
|
||||
course_modes = CourseMode.modes_for_course(
|
||||
course_key,
|
||||
include_expired=True
|
||||
include_expired=True,
|
||||
exclude_credit=False
|
||||
)
|
||||
return [
|
||||
ModeSerializer(mode).data
|
||||
|
||||
Reference in New Issue
Block a user