diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index ad2f810b1f..52fcbb0152 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -304,7 +304,7 @@ def change_enrollment(request): try: course = course_from_id(course_id) except ItemNotFoundError: - log.warning("User {0} tried to enroll in non-existant course {1}" + log.warning("User {0} tried to enroll in non-existent course {1}" .format(user.username, enrollment.course_id)) return {'success': False, 'error': 'The course requested does not exist.'} @@ -595,6 +595,92 @@ def create_account(request, post_override=None): js = {'success': True} return HttpResponse(json.dumps(js), mimetype="application/json") +@login_required +@ensure_csrf_cookie +def begin_test_registration(request, course_id): + user = request.user + + # we want to populate the registration page with the relevant information, + # if it already exists. Create an empty object otherwise. + try: + testcenteruser = TestCenterUser.objects.get(user=user) + except TestCenterUser.DoesNotExist: + testcenteruser = TestCenterUser() + testcenteruser.user = user + + try: + course = (course_from_id(course_id)) + except ItemNotFoundError: + log.error("User {0} enrolled in non-existent course {1}" + .format(user.username, course_id)) + + # placeholder for possible messages... + message = "" + if not user.is_active: + message = render_to_string('registration/activate_account_notice.html', {'email': user.email}) + + context = {'course': course, + 'user': user, + 'message': message, + 'testcenteruser': testcenteruser, + } + + return render_to_response('test_center_register.html', context) + + +def _do_create_or_update_test_center_user(post_vars): + """ + Given cleaned post variables, create the TestCenterUser and UserProfile objects, as well as the + registration for this user. + + Returns a tuple (User, UserProfile, TestCenterUser). + + Note: this function is also used for creating test users. + """ + user = User(username=post_vars['username'], + email=post_vars['email'], + is_active=False) + user.set_password(post_vars['password']) + registration = Registration() + # TODO: Rearrange so that if part of the process fails, the whole process fails. + # Right now, we can have e.g. no registration e-mail sent out and a zombie account + try: + user.save() + except IntegrityError: + js = {'success': False} + # Figure out the cause of the integrity error + if len(User.objects.filter(username=post_vars['username'])) > 0: + js['value'] = "An account with this username already exists." + js['field'] = 'username' + return HttpResponse(json.dumps(js)) + + if len(User.objects.filter(email=post_vars['email'])) > 0: + js['value'] = "An account with this e-mail already exists." + js['field'] = 'email' + return HttpResponse(json.dumps(js)) + + raise + + registration.register(user) + + profile = UserProfile(user=user) + profile.name = post_vars['name'] + profile.level_of_education = post_vars.get('level_of_education') + profile.gender = post_vars.get('gender') + profile.mailing_address = post_vars.get('mailing_address') + profile.goals = post_vars.get('goals') + + try: + profile.year_of_birth = int(post_vars['year_of_birth']) + except (ValueError, KeyError): + profile.year_of_birth = None # If they give us garbage, just ignore it instead + # of asking them to put an integer. + try: + profile.save() + except Exception: + log.exception("UserProfile creation failed for user {0}.".format(user.id)) + return (user, profile, registration) + @ensure_csrf_cookie def create_test_registration(request, post_override=None): ''' diff --git a/common/lib/xmodule/xmodule/course_module.py b/common/lib/xmodule/xmodule/course_module.py index 3506c72bd7..a4cf87b333 100644 --- a/common/lib/xmodule/xmodule/course_module.py +++ b/common/lib/xmodule/xmodule/course_module.py @@ -316,6 +316,18 @@ class CourseDescriptor(SequenceDescriptor): """ return self.metadata.get('end_of_course_survey_url') + @property + def testcenter_info(self): + """ + Pull from policy. + + TODO: decide if we expect this entry to be a single test, or if multiple tests are possible + per course. + + Returns None if no testcenter info specified. + """ + return self.metadata.get('testcenter_info') + @property def title(self): return self.display_name diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index f8e4b2ab57..f771f3e098 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -7,7 +7,6 @@ <%inherit file="main.html" /> <%namespace name='static' file='static_content.html'/> -<%include file="test_center_register_modal.html" /> <%block name="title">Dashboard @@ -221,22 +220,31 @@ -
- Register for Pearson exam -

Registration for the Pearson exam is now open.

-
+ <% + testcenter_info = course.testcenter_info + %> + % if testcenter_info is not None: + + <% + testcenter_register_target = reverse('begin_test_registration', args=[course.id]) + %> +
+ Register for Pearson exam +

Registration for the Pearson exam is now open.

+
-
-

Your registration for the Pearson exam is pending. Within a few days, you should receive a confirmation number, which can be used to schedule your exam.

-
+
+

Your registration for the Pearson exam is pending. Within a few days, you should receive a confirmation number, which can be used to schedule your exam.

+
-
- Schedule Pearson exam -

Registration number: edx00015879548

-

Write this down! You’ll need it to schedule your exam.

-
+
+ Schedule Pearson exam +

Registration number: edx00015879548

+

Write this down! You’ll need it to schedule your exam.

+
- + % endif <% cert_status = cert_statuses.get(course.id) diff --git a/lms/templates/test_center_register.html b/lms/templates/test_center_register.html new file mode 100644 index 0000000000..c71c40610d --- /dev/null +++ b/lms/templates/test_center_register.html @@ -0,0 +1,179 @@ +<%! + from django.core.urlresolvers import reverse + from courseware.courses import course_image_url, get_course_about_section + from courseware.access import has_access + from certificates.models import CertificateStatuses +%> +<%inherit file="main.html" /> + +<%namespace name='static' file='static_content.html'/> + +<%block name="title">Sign Up for Pearson VUE Test Center Proctoring + +<%block name="js_extra"> + + + +
+ + + %if message: +
+ ${message} +
+ %endif + +
+
+
+

+
+
+ + + +
+
+

+ % if course.has_ended(): + Course Completed - ${course.end_date_text} + % elif course.has_started(): + Course Started - ${course.start_date_text} + % else: # hasn't started yet + Course Starts - ${course.start_date_text} + % endif +

+

${get_course_about_section(course, 'university')}

+

${course.number} ${course.title}

+
+ + + <% + testcenter_info = course.testcenter_info + %> + % if testcenter_info is not None: + <% + exam_info = testcenter_info.get('Final_Exam') + %> +

Exam Series Code: ${exam_info.get('Exam_Series_Code')}

+

First Eligible Appointment Date: ${exam_info.get('First_Eligible_Appointment_Date')}

+

Last Eligible Appointment Date: ${exam_info.get('Last_Eligible_Appointment_Date')}

+ % endif + +
+ + +
+
+ + +
+ + + + + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+ +
+ + +
+ + +
+ + +
+ + + + + +
+ + + + +
+ +
+ + + + + + +
+ + + + +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+ +
+
+ + + + \ No newline at end of file diff --git a/lms/urls.py b/lms/urls.py index 97f4613b8f..e81e25e86a 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -43,6 +43,7 @@ urlpatterns = ('', url(r'^create_account$', 'student.views.create_account'), url(r'^activate/(?P[^/]*)$', 'student.views.activate_account', name="activate"), + url(r'^begin_test_registration/(?P[^/]+/[^/]+/[^/]+)$', 'student.views.begin_test_registration', name="begin_test_registration"), url(r'^create_test_registration$', 'student.views.create_test_registration'), url(r'^password_reset/$', 'student.views.password_reset', name='password_reset'),