Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
50f920be
Commit
50f920be
authored
Jul 31, 2015
by
Renzo Lucioni
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #9135 from edx/renzo/always-allow-unenrollment
Allow enrollments in expired modes to be deactivated
parents
614baab3
4131aa4d
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
46 additions
and
9 deletions
+46
-9
common/djangoapps/enrollment/api.py
+19
-7
common/djangoapps/enrollment/serializers.py
+5
-1
common/djangoapps/enrollment/tests/test_views.py
+21
-0
common/djangoapps/enrollment/views.py
+1
-1
No files found.
common/djangoapps/enrollment/api.py
View file @
50f920be
...
...
@@ -137,9 +137,11 @@ def add_enrollment(user_id, course_id, mode='honor', is_active=True):
Enrolls a user in a course. If the mode is not specified, this will default to 'honor'.
Args:
Arg
ument
s:
user_id (str): The user to enroll.
course_id (str): The course to enroll the user in.
Keyword Arguments:
mode (str): Optional argument for the type of enrollment to create. Ex. 'audit', 'honor', 'verified',
'professional'. If not specified, this defaults to 'honor'.
is_active (boolean): Optional argument for making the new enrollment inactive. If not specified, is_active
...
...
@@ -177,7 +179,7 @@ def add_enrollment(user_id, course_id, mode='honor', is_active=True):
}
}
"""
_validate_course_mode
(
course_id
,
mode
)
_validate_course_mode
(
course_id
,
mode
,
is_active
=
is_active
)
return
_data_api
()
.
create_course_enrollment
(
user_id
,
course_id
,
mode
,
is_active
)
...
...
@@ -186,11 +188,14 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None, enrollment_
Update a course enrollment for the given user and course.
Args:
Arg
ument
s:
user_id (str): The user associated with the updated enrollment.
course_id (str): The course associated with the updated enrollment.
Keyword Arguments:
mode (str): The new course mode for this enrollment.
is_active (bool): Sets whether the enrollment is active or not.
enrollment_attributes (list): Attributes to be set the enrollment.
Returns:
A serializable dictionary representing the updated enrollment.
...
...
@@ -226,7 +231,7 @@ def update_enrollment(user_id, course_id, mode=None, is_active=None, enrollment_
"""
if
mode
is
not
None
:
_validate_course_mode
(
course_id
,
mode
)
_validate_course_mode
(
course_id
,
mode
,
is_active
=
is_active
)
enrollment
=
_data_api
()
.
update_course_enrollment
(
user_id
,
course_id
,
mode
=
mode
,
is_active
=
is_active
)
if
enrollment
is
None
:
msg
=
u"Course Enrollment not found for user {user} in course {course}"
.
format
(
user
=
user_id
,
course
=
course_id
)
...
...
@@ -353,7 +358,7 @@ def get_enrollment_attributes(user_id, course_id):
return
_data_api
()
.
get_enrollment_attributes
(
user_id
,
course_id
)
def
_validate_course_mode
(
course_id
,
mode
):
def
_validate_course_mode
(
course_id
,
mode
,
is_active
=
None
):
"""Checks to see if the specified course mode is valid for the course.
If the requested course mode is not available for the course, raise an error with corresponding
...
...
@@ -363,17 +368,24 @@ def _validate_course_mode(course_id, mode):
'honor', return true, allowing the enrollment to be 'honor' even if the mode is not explicitly
set for the course.
Args:
Arg
ument
s:
course_id (str): The course to check against for available course modes.
mode (str): The slug for the course mode specified in the enrollment.
Keyword Arguments:
is_active (bool): Whether the enrollment is to be activated or deactivated.
Returns:
None
Raises:
CourseModeNotFound: raised if the course mode is not found.
"""
course_enrollment_info
=
_data_api
()
.
get_course_enrollment_info
(
course_id
)
# If the client has requested an enrollment deactivation, we want to include expired modes
# in the set of available modes. This allows us to unenroll users from expired modes.
include_expired
=
not
is_active
if
is_active
is
not
None
else
False
course_enrollment_info
=
_data_api
()
.
get_course_enrollment_info
(
course_id
,
include_expired
=
include_expired
)
course_modes
=
course_enrollment_info
[
"course_modes"
]
available_modes
=
[
m
[
'slug'
]
for
m
in
course_modes
]
if
mode
not
in
available_modes
:
...
...
common/djangoapps/enrollment/serializers.py
View file @
50f920be
...
...
@@ -40,7 +40,11 @@ class CourseField(serializers.RelatedField):
def
to_native
(
self
,
course
,
**
kwargs
):
course_modes
=
ModeSerializer
(
CourseMode
.
modes_for_course
(
course
.
id
,
kwargs
.
get
(
'include_expired'
,
False
),
only_selectable
=
False
)
CourseMode
.
modes_for_course
(
course
.
id
,
include_expired
=
kwargs
.
get
(
'include_expired'
,
False
),
only_selectable
=
False
)
)
.
data
# pylint: disable=no-member
return
{
...
...
common/djangoapps/enrollment/tests/test_views.py
View file @
50f920be
...
...
@@ -18,6 +18,7 @@ from django.conf import settings
from
xmodule.modulestore.tests.django_utils
import
ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
,
check_mongo_calls_range
from
django.test.utils
import
override_settings
import
pytz
from
course_modes.models
import
CourseMode
from
embargo.models
import
CountryAccessRule
,
Country
,
RestrictedCourse
...
...
@@ -716,6 +717,26 @@ class EnrollmentTest(EnrollmentTestMixin, ModuleStoreTestCase, APITestCase):
expected_status
=
expected_status
,
)
def
test_deactivate_enrollment_expired_mode
(
self
):
"""Verify that an enrollment in an expired mode can be deactivated."""
for
mode
in
(
CourseMode
.
HONOR
,
CourseMode
.
VERIFIED
):
CourseModeFactory
.
create
(
course_id
=
self
.
course
.
id
,
mode_slug
=
mode
,
mode_display_name
=
mode
,
)
# Create verified enrollment.
self
.
assert_enrollment_status
(
as_server
=
True
,
mode
=
CourseMode
.
VERIFIED
)
# Change verified mode expiration.
mode
=
CourseMode
.
objects
.
get
(
course_id
=
self
.
course
.
id
,
mode_slug
=
CourseMode
.
VERIFIED
)
mode
.
expiration_datetime
=
datetime
.
datetime
(
year
=
1970
,
month
=
1
,
day
=
1
,
tzinfo
=
pytz
.
utc
)
mode
.
save
()
# Deactivate enrollment.
self
.
assert_enrollment_activation
(
False
,
CourseMode
.
VERIFIED
)
def
test_change_mode_from_user
(
self
):
"""Users should not be able to alter the enrollment mode on an enrollment. """
# Create an honor and verified mode for a course. This allows an update.
...
...
common/djangoapps/enrollment/views.py
View file @
50f920be
...
...
@@ -598,7 +598,7 @@ class EnrollmentListView(APIView, ApiKeyPermissionMixIn):
data
=
{
"message"
:
(
u"The course mode '{mode}' is not available for course '{course_id}'."
)
.
format
(
mode
=
"honor"
,
course_id
=
course_id
),
)
.
format
(
mode
=
mode
,
course_id
=
course_id
),
"course_details"
:
error
.
data
})
except
CourseNotFoundError
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment