Allow author to cap enrollments in course

add a test case for enrollment caps

pep8 fix
This commit is contained in:
Chris Dodge
2013-12-16 15:19:59 -05:00
parent 0f8919a6ba
commit ad7348ec11
9 changed files with 96 additions and 4 deletions

View File

@@ -193,6 +193,8 @@ it pauses on the end time.
Blades: Disallow users to enter video url's in http.
Studio/LMS: Ability to cap the max number of active enrollments in a course
LMS: Improve the acessibility of the forum follow post buttons.
Blades: Latex problems are now enabled via use_latex_compiler

View File

@@ -424,6 +424,28 @@ class CourseEnrollment(models.Model):
return enrollment
@classmethod
def num_enrolled_in(cls, course_id):
"""
Returns the count of active enrollments in a course.
'course_id' is the course_id to return enrollments
"""
enrollment_number = CourseEnrollment.objects.filter(course_id=course_id, is_active=1).count()
return enrollment_number
@classmethod
def is_course_full(cls, course):
"""
Returns a boolean value regarding whether a course has already reached it's max enrollment
capacity
"""
is_course_full = False
if course.max_student_enrollments_allowed is not None:
is_course_full = cls.num_enrolled_in(course.location.course_id) >= course.max_student_enrollments_allowed
return is_course_full
def update_enrollment(self, mode=None, is_active=None):
"""
Updates an enrollment for a user in a class. This includes options

View File

@@ -561,6 +561,12 @@ def change_enrollment(request):
if not has_access(user, course, 'enroll'):
return HttpResponseBadRequest(_("Enrollment is closed"))
# see if we have already filled up all allowed enrollments
is_course_full = CourseEnrollment.is_course_full(course)
if is_course_full:
return HttpResponseBadRequest(_("Course is full"))
# If this course is available in multiple modes, redirect them to a page
# where they can choose which mode they want.
available_modes = CourseMode.modes_for_course(course_id)

View File

@@ -13,7 +13,7 @@ from xmodule.seq_module import SequenceDescriptor, SequenceModule
from xmodule.graders import grader_from_conf
import json
from xblock.fields import Scope, List, String, Dict, Boolean
from xblock.fields import Scope, List, String, Dict, Boolean, Integer
from .fields import Date
from xmodule.modulestore.locator import CourseLocator
from django.utils.timezone import UTC
@@ -384,6 +384,9 @@ class CourseFields(object):
display_coursenumber = String(help="An optional display string for the course number that will get rendered in the LMS",
scope=Scope.settings)
max_student_enrollments_allowed = Integer(help="Limit the number of students allowed to enroll in this course.",
scope=Scope.settings)
class CourseDescriptor(CourseFields, SequenceDescriptor):
module_class = SequenceModule

View File

@@ -51,3 +51,54 @@ class AboutTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn(self.xml_data, resp.content)
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
class AboutWithCappedEnrollmentsTestCase(LoginEnrollmentTestCase, ModuleStoreTestCase):
"""
This test case will check the About page when a course has a capped enrollment
"""
def setUp(self):
"""
Set up the tests
"""
self.course = CourseFactory.create(metadata={"max_student_enrollments_allowed": 1})
self.about = ItemFactory.create(
category="about", parent_location=self.course.location,
data="OOGIE BLOOGIE", display_name="overview"
)
# The following XML course is closed; we're testing that
# an about page still appears when the course is already closed
self.xml_course_id = 'edX/detached_pages/2014'
self.xml_data = "about page 463139"
def test_enrollment_cap(self):
"""
This test will make sure that enrollment caps are enforced
"""
self.setup_user()
url = reverse('about_course', args=[self.course.id])
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn('<a href="#" class="register">', resp.content)
self.enroll(self.course, verify=True)
# create a new account since the first account is already registered for the course
self.email = 'foo_second@test.com'
self.password = 'bar'
self.username = 'test_second'
self.create_account(self.username,
self.email, self.password)
self.activate_user(self.email)
self.login(self.email, self.password)
# Get the about page again and make sure that the page says that the course is full
resp = self.client.get(url)
self.assertEqual(resp.status_code, 200)
self.assertIn("Course is full", resp.content)
# Try to enroll as well
result = self.enroll(self.course)
self.assertFalse(result)

View File

@@ -562,6 +562,9 @@ def course_about(request, course_id):
reg_then_add_to_cart_link = "{reg_url}?course_id={course_id}&enrollment_action=add_to_cart".format(
reg_url=reverse('register_user'), course_id=course.id)
# see if we have already filled up all allowed enrollments
is_course_full = CourseEnrollment.is_course_full(course)
return render_to_response('courseware/course_about.html',
{'course': course,
'registered': registered,
@@ -569,7 +572,8 @@ def course_about(request, course_id):
'registration_price': registration_price,
'in_cart': in_cart,
'reg_then_add_to_cart_link': reg_then_add_to_cart_link,
'show_courseware_link': show_courseware_link})
'show_courseware_link': show_courseware_link,
'is_course_full': is_course_full})
@ensure_csrf_cookie

View File

@@ -115,7 +115,7 @@ def _section_course_info(course_id, access):
'course_num': course_num,
'course_name': course_name,
'course_display_name': course.display_name,
'enrollment_count': CourseEnrollment.objects.filter(course_id=course_id, is_active=1).count(),
'enrollment_count': CourseEnrollment.num_enrolled_in(course_id),
'has_started': course.has_started(),
'has_ended': course.has_ended(),
'list_instructor_tasks_url': reverse('list_instructor_tasks', kwargs={'course_id': course_id}),

View File

@@ -110,7 +110,7 @@ def instructor_dashboard(request, course_id):
else:
idash_mode = request.session.get('idash_mode', 'Grades')
enrollment_number = CourseEnrollment.objects.filter(course_id=course_id, is_active=1).count()
enrollment_number = CourseEnrollment.num_enrolled_in(course_id)
# assemble some course statistics for output to instructor
def get_course_stats_table():

View File

@@ -166,6 +166,10 @@
cost=registration_price)}
</a>
<div id="register_error"></div>
% elif is_course_full:
<span class="register disabled">
${_("Course is full")}
</span>
%else:
<a href="#" class="register">
${_("Register for {course.display_number_with_default}").format(course=course) | h}