From d5bd2313c1baaa395bda60868f467577387a4d8b Mon Sep 17 00:00:00 2001 From: Brian Wilson <brian@edx.org> Date: Thu, 20 Dec 2012 04:16:00 -0500 Subject: [PATCH] fix migrations, removing one field and making another nullable. Update registration page to allow for editing only demographics. --- ...022_add_more_fields_to_test_center_user.py | 15 ++-- common/djangoapps/student/models.py | 13 +-- common/djangoapps/student/views.py | 73 ++++++++++------- lms/templates/dashboard.html | 3 +- lms/templates/test_center_register.html | 80 ++++++++++++++++--- 5 files changed, 128 insertions(+), 56 deletions(-) diff --git a/common/djangoapps/student/migrations/0022_add_more_fields_to_test_center_user.py b/common/djangoapps/student/migrations/0022_add_more_fields_to_test_center_user.py index 4a6481f80cc..1bffec22130 100644 --- a/common/djangoapps/student/migrations/0022_add_more_fields_to_test_center_user.py +++ b/common/djangoapps/student/migrations/0022_add_more_fields_to_test_center_user.py @@ -13,8 +13,8 @@ class Migration(SchemaMigration): self.gf('django.db.models.fields.CharField')(default='', max_length=20, blank=True), keep_default=False) - # Adding field 'TestCenterUser.confirmed_at' - db.add_column('student_testcenteruser', 'confirmed_at', + # Adding field 'TestCenterUser.uploaded_at' + db.add_column('student_testcenteruser', 'uploaded_at', self.gf('django.db.models.fields.DateTimeField')(null=True, db_index=True), keep_default=False) @@ -31,14 +31,13 @@ class Migration(SchemaMigration): ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, db_index=True, blank=True)), ('updated_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, db_index=True, blank=True)), ('user_updated_at', self.gf('django.db.models.fields.DateTimeField')(db_index=True)), - ('client_authorization_id', self.gf('django.db.models.fields.CharField')(unique=True, max_length=20, db_index=True)), ('exam_series_code', self.gf('django.db.models.fields.CharField')(max_length=15, db_index=True)), ('eligibility_appointment_date_first', self.gf('django.db.models.fields.DateField')(db_index=True)), ('eligibility_appointment_date_last', self.gf('django.db.models.fields.DateField')(db_index=True)), ('accommodation_code', self.gf('django.db.models.fields.CharField')(max_length=64, blank=True)), ('accommodation_request', self.gf('django.db.models.fields.CharField')(max_length=1024, blank=True)), ('upload_status', self.gf('django.db.models.fields.CharField')(max_length=20, blank=True)), - ('confirmed_at', self.gf('django.db.models.fields.DateTimeField')(db_index=True)), + ('uploaded_at', self.gf('django.db.models.fields.DateTimeField')(null=True, db_index=True)), ('upload_error_message', self.gf('django.db.models.fields.CharField')(max_length=512, blank=True)), )) db.send_create_signal('student', ['TestCenterRegistration']) @@ -51,8 +50,8 @@ class Migration(SchemaMigration): # Deleting field 'TestCenterUser.upload_status' db.delete_column('student_testcenteruser', 'upload_status') - # Deleting field 'TestCenterUser.confirmed_at' - db.delete_column('student_testcenteruser', 'confirmed_at') + # Deleting field 'TestCenterUser.uploaded_at' + db.delete_column('student_testcenteruser', 'uploaded_at') # Deleting field 'TestCenterUser.upload_error_message' db.delete_column('student_testcenteruser', 'upload_error_message') @@ -127,7 +126,7 @@ class Migration(SchemaMigration): 'accommodation_code': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'accommodation_request': ('django.db.models.fields.CharField', [], {'max_length': '1024', 'blank': 'True'}), 'client_authorization_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', 'db_index': 'True'}), - 'confirmed_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), + 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}), 'course_id': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}), 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), 'eligibility_appointment_date_first': ('django.db.models.fields.DateField', [], {'db_index': 'True'}), @@ -149,7 +148,7 @@ class Migration(SchemaMigration): 'city': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}), 'client_candidate_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}), 'company_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), - 'confirmed_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}), + 'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}), 'country': ('django.db.models.fields.CharField', [], {'max_length': '3', 'db_index': 'True'}), 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}), 'extension': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '8', 'blank': 'True'}), diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index 6b73c2319fc..716c472330e 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -194,7 +194,7 @@ class TestCenterUser(models.Model): # Confirmation upload_status = models.CharField(max_length=20, blank=True) # 'Error' or 'Accepted' - confirmed_at = models.DateTimeField(null=True, db_index=True) + uploaded_at = models.DateTimeField(null=True, db_index=True) upload_error_message = models.CharField(max_length=512, blank=True) @staticmethod @@ -236,7 +236,7 @@ class TestCenterRegistration(models.Model): user_updated_at = models.DateTimeField(db_index=True) # "client_authorization_id" is the client's unique identifier for the authorization. # This must be present for an update or delete to be sent to Pearson. - client_authorization_id = models.CharField(max_length=20, unique=True, db_index=True) + # client_authorization_id = models.CharField(max_length=20, unique=True, db_index=True) # information about the test, from the course policy: exam_series_code = models.CharField(max_length=15, db_index=True) @@ -250,7 +250,7 @@ class TestCenterRegistration(models.Model): # Confirmation upload_status = models.CharField(max_length=20, blank=True) # 'Error' or 'Accepted' - confirmed_at = models.DateTimeField(db_index=True) + uploaded_at = models.DateTimeField(null=True, db_index=True) upload_error_message = models.CharField(max_length=512, blank=True) @property @@ -261,12 +261,15 @@ class TestCenterRegistration(models.Model): def client_candidate_id(self): return self.testcenter_user.client_candidate_id - + @property + def client_authorization_id(self): + # TODO: make this explicitly into a string object: + return self.id def get_testcenter_registrations_for_user_and_course(user, course_id): try: tcu = TestCenterUser.objects.get(user=user) - except User.DoesNotExist: + except TestCenterUser.DoesNotExist: return [] return TestCenterRegistration.objects.filter(testcenter_user=tcu, course_id=course_id) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 4d5728792e3..62943478a01 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -10,6 +10,7 @@ import sys import urllib import uuid + from django.conf import settings from django.contrib.auth import logout, authenticate, login from django.contrib.auth.forms import PasswordResetForm @@ -17,6 +18,7 @@ from django.contrib.auth.models import User from django.contrib.auth.decorators import login_required from django.core.context_processors import csrf from django.core.mail import send_mail +from django.core.urlresolvers import reverse from django.core.validators import validate_email, validate_slug, ValidationError from django.db import IntegrityError from django.http import HttpResponse, HttpResponseForbidden, Http404,\ @@ -29,7 +31,8 @@ from django.core.cache import cache from django_future.csrf import ensure_csrf_cookie, csrf_exempt from student.models import (Registration, UserProfile, TestCenterUser, TestCenterRegistration, PendingNameChange, PendingEmailChange, - CourseEnrollment, unique_id_for_user) + CourseEnrollment, unique_id_for_user, + get_testcenter_registrations_for_user_and_course) from certificates.models import CertificateStatuses, certificate_status_for_student @@ -617,11 +620,7 @@ def begin_test_registration(request, course_id): log.error("User {0} enrolled in non-existent course {1}" .format(user.username, course_id)) - # TODO: 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, @@ -676,7 +675,7 @@ def _do_create_or_update_test_center_user(post_vars): try: testcenter_user.save() except IntegrityError, ie: - message = ie + message = "%s" % ie context = {'course': course, 'user': user, 'message': message, @@ -685,31 +684,45 @@ def _do_create_or_update_test_center_user(post_vars): return render_to_response('test_center_register.html', context) # create and save the registration: - registration = TestCenterRegistration(testcenter_user = testcenter_user) - registration.course_id = post_vars['course_id'] - registration.accommodation_request = post_vars['accommodations'] - exam_info = course.testcenter_info - registration.exam_series_code = exam_info.get('Exam_Series_Code') - registration.eligibility_appointment_date_first = exam_info.get('First_Eligible_Appointment_Date') - registration.eligibility_appointment_date_last = exam_info.get('Last_Eligible_Appointment_Date') - # accommodation_code remains blank for now, along with Pearson confirmation - registration.user_updated_at = datetime.datetime.now() - + needs_saving = False + registrations = get_testcenter_registrations_for_user_and_course(user, course.id) + # In future, this should check the exam series code of the registrations, if there + # were multiple. + if len(registrations) > 0: + registration = registrations[0] + # check to see if registration changed. Should check appointment dates too... + # And later should check changes in accommodation_code. + # But at the moment, we don't expect anything to cause this to change + # right now. + + else: + registration = TestCenterRegistration(testcenter_user = testcenter_user) + registration.course_id = post_vars['course_id'] + registration.accommodation_request = post_vars['accommodations'] + exam_info = course.testcenter_info + registration.exam_series_code = exam_info.get('Exam_Series_Code') + registration.eligibility_appointment_date_first = exam_info.get('First_Eligible_Appointment_Date') + registration.eligibility_appointment_date_last = exam_info.get('Last_Eligible_Appointment_Date') + # accommodation_code remains blank for now, along with Pearson confirmation + registration.user_updated_at = datetime.datetime.now() + needs_saving = True + # "client_authorization_id" is the client's unique identifier for the authorization. - # This must be present for an update or delete to be sent to Pearson. - registration.client_authorization_id = "1" - try: - registration.save() - except IntegrityError, ie: - message = ie - context = {'course': course, - 'user': user, - 'message': message, - 'testcenteruser': testcenter_user, - } - return render_to_response('test_center_register.html', context) + # This must be present for an update or delete to be sent to Pearson. + # Can we just use the id field of the registration? Lets... + + if needs_saving: + try: + registration.save() + except IntegrityError, ie: + message = "%s" % ie + context = {'course': course, + 'user': user, + 'message': message, + 'testcenteruser': testcenter_user, + } + return render_to_response('test_center_register.html', context) - return (user, testcenter_user, registration) @ensure_csrf_cookie @@ -778,7 +791,7 @@ def create_test_registration(request, post_override=None): # js = {'success': True} # return HttpResponse(json.dumps(js), mimetype="application/json") - return HttpResponseRedirect('/dashboard') + return HttpResponseRedirect(reverse('dashboard')) def get_random_post_override(): """ diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html index 13e393180a6..1f1553d90c9 100644 --- a/lms/templates/dashboard.html +++ b/lms/templates/dashboard.html @@ -234,8 +234,7 @@ %> % if len(registrations) == 0: <div class="message message-status is-shown exam-register"> -<!-- <a href="#testcenter-register-modal" rel="leanModal" class="exam-button" data-course-id="${course.id}" data-course-number="${course.number}" id="exam_register_button">Register for Pearson exam</a> ---> <a href="${testcenter_register_target}" class="exam-button" id="exam_register_button">Register for Pearson exam</a> + <a href="${testcenter_register_target}" class="exam-button" id="exam_register_button">Register for Pearson exam</a> <p class="message-copy">Registration for the Pearson exam is now open.</p> </div> % else: diff --git a/lms/templates/test_center_register.html b/lms/templates/test_center_register.html index 51b271dfc33..8c99b4f8ef0 100644 --- a/lms/templates/test_center_register.html +++ b/lms/templates/test_center_register.html @@ -3,6 +3,7 @@ from courseware.courses import course_image_url, get_course_about_section from courseware.access import has_access from certificates.models import CertificateStatuses + from student.models import get_testcenter_registrations_for_user_and_course %> <%inherit file="main.html" /> @@ -34,14 +35,7 @@ </script> </%block> -<section id="testcenter-register" class=""> - - - %if message: - <section class="dashboard-banner"> - ${message} - </section> - %endif +<section id="testcenter-register" class=""> <div class="inner-wrapper"> <div id="register"> @@ -81,7 +75,63 @@ </section> - + <!-- check to see if the user has already registering, or + is registering for the first time --> + <% + registrations = get_testcenter_registrations_for_user_and_course(user, course.id) + %> + + % if len(registrations) > 0: + <% + registration = registrations[0] + %> + + <section><div>Already Registered</div> + <p>Here is the current state of your registration, for debugging purposes:</p> + <l> + <li>id: ${registration.id}</li> + <li>testcenter_user_id: ${registration.testcenter_user_id}</li> + <li>course_id: ${registration.course_id}</li> + <li>accommodation codes: ${registration.accommodation_code}</li> + <li>accommodation request: ${registration.accommodation_request}</li> + <li>created_at: ${registration.created_at}</li> + <li>updated_at: ${registration.updated_at}</li> + <li>user_updated_at: ${registration.user_updated_at}</li> + <li>upload_status: ${registration.upload_status}</li> + <li>upload_error_message: ${registration.upload_error_message}</li> + </l> + + + <!-- determine status of registration + doing here for now, but will move into model or view --> + <% + regstatus = "registration pending acknowledgement by Pearson" + + if registration.upload_status == 'Accepted': + regstatus = "registration approved by Pearson" + elif registration.upload_status == 'Error': + regstatus = "registration rejected by Pearson: %s" % registration.upload_error_message + elif len(registration.accommodation_request) > 0 and registration.accommodation_code == '': + regstatus = "pending approval of accommodation request" + %> + <p>Current status: ${regstatus}</p> + + <p>The demographic information provided below was used to register + for the exam listed above. Changes to this information + may be submitted below.</p> + </section> + % else: + <p>The demographic information must be provided below in order to register + for the exam listed above.</p> + % endif + + <!-- provide mechanism for error messages to appear --> + % if message: + <section class=""> + <p>${message}</p> + </section> + % endif + <form id="test_register_form" class="test_register_form" method="post" data-remote="true" action="/create_test_registration"> <div class="notice"></div> <!-- TODO: why are both of these here? --> @@ -91,7 +141,6 @@ <!-- include these as pass-throughs --> <input id="id_email" type="hidden" name="email" maxlength="75" value="${user.email}" /> <input id="id_username" type="hidden" name="username" maxlength="75" value="${user.username}" /> - <!-- TODO: add the course somehow... --> <input id="id_course_id" type="hidden" name="course_id" maxlength="75" value="${course.id}" /> <div class="input-group"> @@ -150,15 +199,24 @@ <label data-field="company_name">Company</label> <input name="company_name" type="text" value="${testcenteruser.company_name}" placeholder="Acme Corporation"> </div> - + <div><p>The following is included here just so it can be input within the form. But it + is not part of the demographics, and it is not something that can be changed once input.</p> + </div> <div class="input-group"> <label data-field="accommodations">Accommodations Requested</label> <textarea name="accommodations"></textarea> </div> + % if len(registrations) > 0: + <div class="submit"> + <input name="submit" type="submit" value="Update demographics"> + </div> + % else: <div class="submit"> <input name="submit" type="submit" value="Register for Test"> </div> + % endif + </form> </div> -- GitLab