Commit ea8a56da by Brian Wilson

add id generation and validation

parent e32dfcf0
...@@ -8,29 +8,15 @@ from django.db import models ...@@ -8,29 +8,15 @@ from django.db import models
class Migration(SchemaMigration): class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding field 'TestCenterUser.upload_status'
db.add_column('student_testcenteruser', 'upload_status',
self.gf('django.db.models.fields.CharField')(default='', max_length=20, blank=True),
keep_default=False)
# 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)
# Adding field 'TestCenterUser.upload_error_message'
db.add_column('student_testcenteruser', 'upload_error_message',
self.gf('django.db.models.fields.CharField')(default='', max_length=512, blank=True),
keep_default=False)
# Adding model 'TestCenterRegistration' # Adding model 'TestCenterRegistration'
db.create_table('student_testcenterregistration', ( db.create_table('student_testcenterregistration', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('testcenter_user', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['student.TestCenterUser'], unique=True)), ('testcenter_user', self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['student.TestCenterUser'])),
('course_id', self.gf('django.db.models.fields.CharField')(max_length=128, db_index=True)), ('course_id', self.gf('django.db.models.fields.CharField')(max_length=128, db_index=True)),
('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, db_index=True, blank=True)), ('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)), ('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)), ('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)), ('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_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)), ('eligibility_appointment_date_last', self.gf('django.db.models.fields.DateField')(db_index=True)),
...@@ -42,8 +28,35 @@ class Migration(SchemaMigration): ...@@ -42,8 +28,35 @@ class Migration(SchemaMigration):
)) ))
db.send_create_signal('student', ['TestCenterRegistration']) db.send_create_signal('student', ['TestCenterRegistration'])
# Adding field 'TestCenterUser.upload_status'
db.add_column('student_testcenteruser', 'upload_status',
self.gf('django.db.models.fields.CharField')(db_index=True, default='', max_length=20, blank=True),
keep_default=False)
# Adding field 'TestCenterUser.uploaded_at'
db.add_column('student_testcenteruser', 'uploaded_at',
self.gf('django.db.models.fields.DateTimeField')(db_index=True, null=True, blank=True),
keep_default=False)
# Adding field 'TestCenterUser.upload_error_message'
db.add_column('student_testcenteruser', 'upload_error_message',
self.gf('django.db.models.fields.CharField')(default='', max_length=512, blank=True),
keep_default=False)
# Adding index on 'TestCenterUser', fields ['company_name']
db.create_index('student_testcenteruser', ['company_name'])
# Adding unique constraint on 'TestCenterUser', fields ['client_candidate_id']
db.create_unique('student_testcenteruser', ['client_candidate_id'])
def backwards(self, orm): def backwards(self, orm):
# Removing unique constraint on 'TestCenterUser', fields ['client_candidate_id']
db.delete_unique('student_testcenteruser', ['client_candidate_id'])
# Removing index on 'TestCenterUser', fields ['company_name']
db.delete_index('student_testcenteruser', ['company_name'])
# Deleting model 'TestCenterRegistration' # Deleting model 'TestCenterRegistration'
db.delete_table('student_testcenterregistration') db.delete_table('student_testcenterregistration')
...@@ -126,17 +139,17 @@ class Migration(SchemaMigration): ...@@ -126,17 +139,17 @@ class Migration(SchemaMigration):
'accommodation_code': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}), 'accommodation_code': ('django.db.models.fields.CharField', [], {'max_length': '64', 'blank': 'True'}),
'accommodation_request': ('django.db.models.fields.CharField', [], {'max_length': '1024', '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'}), 'client_authorization_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20', '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'}), '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'}), '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'}), 'eligibility_appointment_date_first': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
'eligibility_appointment_date_last': ('django.db.models.fields.DateField', [], {'db_index': 'True'}), 'eligibility_appointment_date_last': ('django.db.models.fields.DateField', [], {'db_index': 'True'}),
'exam_series_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}), 'exam_series_code': ('django.db.models.fields.CharField', [], {'max_length': '15', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'testcenter_user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['student.TestCenterUser']", 'unique': 'True'}), 'testcenter_user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['student.TestCenterUser']"}),
'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
'upload_error_message': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'upload_error_message': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'upload_status': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), 'upload_status': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}),
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
'user_updated_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}) 'user_updated_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'})
}, },
'student.testcenteruser': { 'student.testcenteruser': {
...@@ -146,9 +159,8 @@ class Migration(SchemaMigration): ...@@ -146,9 +159,8 @@ class Migration(SchemaMigration):
'address_3': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}), 'address_3': ('django.db.models.fields.CharField', [], {'max_length': '40', 'blank': 'True'}),
'candidate_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'db_index': 'True'}), 'candidate_id': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'db_index': 'True'}),
'city': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}), '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'}), 'client_candidate_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50', 'db_index': 'True'}),
'company_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), 'company_name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '50', 'blank': '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'}), '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'}), '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'}), 'extension': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '8', 'blank': 'True'}),
...@@ -166,7 +178,8 @@ class Migration(SchemaMigration): ...@@ -166,7 +178,8 @@ class Migration(SchemaMigration):
'suffix': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}), 'suffix': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}), 'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
'upload_error_message': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}), 'upload_error_message': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'upload_status': ('django.db.models.fields.CharField', [], {'max_length': '20', 'blank': 'True'}), 'upload_status': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '20', 'blank': 'True'}),
'uploaded_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True', 'null': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['auth.User']", 'unique': 'True'}), 'user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['auth.User']", 'unique': 'True'}),
'user_updated_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}) 'user_updated_at': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'})
}, },
...@@ -194,4 +207,4 @@ class Migration(SchemaMigration): ...@@ -194,4 +207,4 @@ class Migration(SchemaMigration):
} }
} }
complete_apps = ['student'] complete_apps = ['student']
\ No newline at end of file
...@@ -40,6 +40,7 @@ import hashlib ...@@ -40,6 +40,7 @@ import hashlib
import json import json
import logging import logging
import uuid import uuid
from random import randint
from django.conf import settings from django.conf import settings
...@@ -47,10 +48,12 @@ from django.contrib.auth.models import User ...@@ -47,10 +48,12 @@ from django.contrib.auth.models import User
from django.db import models from django.db import models
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from django.forms import ModelForm from django.forms import ModelForm, forms
import comment_client as cc import comment_client as cc
from django_comment_client.models import Role from django_comment_client.models import Role
from feedparser import binascii
import os
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -160,7 +163,7 @@ class TestCenterUser(models.Model): ...@@ -160,7 +163,7 @@ class TestCenterUser(models.Model):
candidate_id = models.IntegerField(null=True, db_index=True) candidate_id = models.IntegerField(null=True, db_index=True)
# Unique ID we assign our user for the Test Center. # Unique ID we assign our user for the Test Center.
client_candidate_id = models.CharField(max_length=50, db_index=True) client_candidate_id = models.CharField(unique=True, max_length=50, db_index=True)
# Name # Name
first_name = models.CharField(max_length=30, db_index=True) first_name = models.CharField(max_length=30, db_index=True)
...@@ -191,10 +194,10 @@ class TestCenterUser(models.Model): ...@@ -191,10 +194,10 @@ class TestCenterUser(models.Model):
fax_country_code = models.CharField(max_length=3, blank=True) fax_country_code = models.CharField(max_length=3, blank=True)
# Company # Company
company_name = models.CharField(max_length=50, blank=True) company_name = models.CharField(max_length=50, blank=True, db_index=True)
# Confirmation # Confirmation
upload_status = models.CharField(max_length=20, blank=True) # 'Error' or 'Accepted' upload_status = models.CharField(max_length=20, blank=True, db_index=True) # 'Error' or 'Accepted'
uploaded_at = models.DateTimeField(null=True, blank=True, db_index=True) uploaded_at = models.DateTimeField(null=True, blank=True, db_index=True)
upload_error_message = models.CharField(max_length=512, blank=True) upload_error_message = models.CharField(max_length=512, blank=True)
...@@ -217,26 +220,21 @@ class TestCenterUser(models.Model): ...@@ -217,26 +220,21 @@ class TestCenterUser(models.Model):
return False return False
# def update(self, dict): @staticmethod
# # leave user and client_candidate_id as before def _generate_candidate_id():
# self.user_updated_at = datetime.now() NUM_DIGITS = 12
# for fieldname in TestCenterUser.user_provided_fields(): return u"edX%0d" % randint(1, 10**NUM_DIGITS-1) # binascii.hexlify(os.urandom(8))
# self.__setattr__(fieldname, dict[fieldname])
# @staticmethod
# def create(user, dict):
# testcenter_user = TestCenterUser(user=user)
# testcenter_user.update(dict)
# # testcenter_user.candidate_id remains unset
# # TODO: assign an ID of our own:
# testcenter_user.client_candidate_id = 'edx' + unique_id_for_user(user) # some unique value
@staticmethod @staticmethod
def create(user): def create(user):
testcenter_user = TestCenterUser(user=user) testcenter_user = TestCenterUser(user=user)
# testcenter_user.candidate_id remains unset # testcenter_user.candidate_id remains unset
# assign an ID of our own: # assign an ID of our own:
testcenter_user.client_candidate_id = 'edx' + unique_id_for_user(user) # some unique value cand_id = TestCenterUser._generate_candidate_id()
while TestCenterUser.objects.filter(client_candidate_id=cand_id).exists():
cand_id = TestCenterUser._generate_candidate_id()
testcenter_user.client_candidate_id = cand_id
return testcenter_user
class TestCenterUserForm(ModelForm): class TestCenterUserForm(ModelForm):
class Meta: class Meta:
...@@ -251,6 +249,60 @@ class TestCenterUserForm(ModelForm): ...@@ -251,6 +249,60 @@ class TestCenterUserForm(ModelForm):
new_user.user_updated_at = datetime.now() new_user.user_updated_at = datetime.now()
new_user.save() new_user.save()
# add validation:
@staticmethod
def can_encode_as_latin(fieldvalue):
try:
fieldvalue.encode('iso-8859-1')
except UnicodeEncodeError:
return False
return True
def check_country_code(self, fieldname):
code = self.cleaned_data[fieldname]
if code and len(code) != 3:
raise forms.ValidationError(u'Must be three characters (ISO 3166-1): e.g. USA, CAN, MNG')
return code
def clean_country(self):
return self.check_country_code('country')
def clean_phone_country_code(self):
return self.check_country_code('phone_country_code')
def clean_fax_country_code(self):
return self.check_country_code('fax_country_code')
def clean(self):
cleaned_data = super(TestCenterUserForm, self).clean()
# check for interactions between fields:
if 'country' in cleaned_data:
country = cleaned_data.get('country')
if country == 'USA' or country == 'CAN':
if 'state' in cleaned_data and len(cleaned_data['state']) == 0:
self._errors['state'] = self.error_class([u'Required if country is USA or CAN.'])
del cleaned_data['state']
if 'postal_code' in cleaned_data and len(cleaned_data['postal_code']) == 0:
self._errors['postal_code'] = self.error_class([u'Required if country is USA or CAN.'])
del cleaned_data['postal_code']
if 'fax' in cleaned_data and len(cleaned_data['fax']) > 0 and 'fax_country_code' in cleaned_data and len(cleaned_data['fax_country_code']) == 0:
self._errors['fax_country_code'] = self.error_class([u'Required if fax is specified.'])
del cleaned_data['fax_country_code']
# check encoding for all fields:
cleaned_data_fields = [fieldname for fieldname in cleaned_data]
for fieldname in cleaned_data_fields:
if not TestCenterUserForm.can_encode_as_latin(cleaned_data[fieldname]):
self._errors[fieldname] = self.error_class([u'Must only use characters in Latin-1 encoding'])
del cleaned_data[fieldname]
# Always return the full collection of cleaned data.
return cleaned_data
ACCOMODATION_CODES = ( ACCOMODATION_CODES = (
...@@ -282,7 +334,7 @@ class TestCenterRegistration(models.Model): ...@@ -282,7 +334,7 @@ class TestCenterRegistration(models.Model):
# to find an exam registration, we key off of the user and course_id. # to find an exam registration, we key off of the user and course_id.
# If multiple exams per course are possible, we would also need to add the # If multiple exams per course are possible, we would also need to add the
# exam_series_code. # exam_series_code.
testcenter_user = models.ForeignKey(TestCenterUser, unique=True, default=None) testcenter_user = models.ForeignKey(TestCenterUser, default=None)
course_id = models.CharField(max_length=128, db_index=True) course_id = models.CharField(max_length=128, db_index=True)
created_at = models.DateTimeField(auto_now_add=True, db_index=True) created_at = models.DateTimeField(auto_now_add=True, db_index=True)
...@@ -295,7 +347,7 @@ class TestCenterRegistration(models.Model): ...@@ -295,7 +347,7 @@ class TestCenterRegistration(models.Model):
user_updated_at = models.DateTimeField(db_index=True) user_updated_at = models.DateTimeField(db_index=True)
# "client_authorization_id" is the client's unique identifier for the authorization. # "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. # 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: # information about the test, from the course policy:
exam_series_code = models.CharField(max_length=15, db_index=True) exam_series_code = models.CharField(max_length=15, db_index=True)
...@@ -311,7 +363,7 @@ class TestCenterRegistration(models.Model): ...@@ -311,7 +363,7 @@ class TestCenterRegistration(models.Model):
# Confirmation # Confirmation
upload_status = models.CharField(max_length=20, blank=True) # 'Error' or 'Accepted' upload_status = models.CharField(max_length=20, blank=True) # 'Error' or 'Accepted'
uploaded_at = models.DateTimeField(null=True, blank=True, db_index=True) uploaded_at = models.DateTimeField(null=True, db_index=True)
upload_error_message = models.CharField(max_length=512, blank=True) upload_error_message = models.CharField(max_length=512, blank=True)
@property @property
...@@ -331,25 +383,26 @@ class TestCenterRegistration(models.Model): ...@@ -331,25 +383,26 @@ class TestCenterRegistration(models.Model):
registration.eligibility_appointment_date_first = exam_info.get('First_Eligible_Appointment_Date') registration.eligibility_appointment_date_first = exam_info.get('First_Eligible_Appointment_Date')
registration.eligibility_appointment_date_last = exam_info.get('Last_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 # accommodation_code remains blank for now, along with Pearson confirmation
registration.user_updated_at = datetime.now() registration.client_authorization_id = registration._create_client_authorization_id()
#registration.client_authorization_id = registration._create_client_authorization_id()
return registration return registration
@staticmethod
def _generate_authorization_id():
NUM_DIGITS = 12
return u"edX%0d" % randint(1, 10**NUM_DIGITS-1) # binascii.hexlify(os.urandom(8))
def _create_client_authorization_id(self): def _create_client_authorization_id(self):
""" """
Return a unique id for a registration, suitable for inserting into Return a unique id for a registration, suitable for using as an authorization code
e.g. personalized survey links. for Pearson. It must fit within 20 characters.
""" """
# include the secret key as a salt, and to make the ids unique across # generate a random value, and check to see if it already is in use here
# different LMS installs. Then add in (user, course, exam), which should auth_id = TestCenterRegistration._generate_authorization_id()
# be unique. while TestCenterRegistration.objects.filter(client_authorization_id=auth_id).exists():
h = hashlib.md5() auth_id = TestCenterRegistration._generate_authorization_id()
h.update(settings.SECRET_KEY) return auth_id
h.update(str(self.testcenter_user.user.id))
h.update(str(self.course_id))
h.update(str(self.exam_series_code))
return h.hexdigest()
def is_accepted(self): def is_accepted(self):
return self.upload_status == 'Accepted' return self.upload_status == 'Accepted'
...@@ -362,7 +415,21 @@ class TestCenterRegistration(models.Model): ...@@ -362,7 +415,21 @@ class TestCenterRegistration(models.Model):
def is_pending_acknowledgement(self): def is_pending_acknowledgement(self):
return self.upload_status == '' and not self.is_pending_accommodation() return self.upload_status == '' and not self.is_pending_accommodation()
class TestCenterRegistrationForm(ModelForm):
class Meta:
model = TestCenterRegistration
fields = ( 'accommodation_request', )
def update_and_save(self):
registration = self.save(commit=False)
# create additional values here:
registration.user_updated_at = datetime.now()
registration.save()
# TODO: add validation code for values added to accommodation_code field.
def get_testcenter_registrations_for_user_and_course(user, course_id, exam_series_code=None): def get_testcenter_registrations_for_user_and_course(user, course_id, exam_series_code=None):
try: try:
tcu = TestCenterUser.objects.get(user=user) tcu = TestCenterUser.objects.get(user=user)
......
...@@ -18,18 +18,17 @@ from django.contrib.auth.models import User ...@@ -18,18 +18,17 @@ from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.core.mail import send_mail 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.core.validators import validate_email, validate_slug, ValidationError
from django.db import IntegrityError from django.db import IntegrityError
from django.http import HttpResponse, HttpResponseForbidden, Http404,\ from django.http import HttpResponse, HttpResponseForbidden, Http404
HttpResponseRedirect
from django.shortcuts import redirect from django.shortcuts import redirect
from mitxmako.shortcuts import render_to_response, render_to_string from mitxmako.shortcuts import render_to_response, render_to_string
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from django.core.cache import cache from django.core.cache import cache
from django_future.csrf import ensure_csrf_cookie, csrf_exempt from django_future.csrf import ensure_csrf_cookie, csrf_exempt
from student.models import (Registration, UserProfile, TestCenterUser, TestCenterUserForm, TestCenterRegistration, from student.models import (Registration, UserProfile, TestCenterUser, TestCenterUserForm,
TestCenterRegistration, TestCenterRegistrationForm,
PendingNameChange, PendingEmailChange, PendingNameChange, PendingEmailChange,
CourseEnrollment, unique_id_for_user, CourseEnrollment, unique_id_for_user,
get_testcenter_registrations_for_user_and_course) get_testcenter_registrations_for_user_and_course)
...@@ -248,8 +247,6 @@ def dashboard(request): ...@@ -248,8 +247,6 @@ def dashboard(request):
'show_courseware_links_for' : show_courseware_links_for, 'show_courseware_links_for' : show_courseware_links_for,
'cert_statuses': cert_statuses, 'cert_statuses': cert_statuses,
'news': top_news, 'news': top_news,
# No longer needed here...move to begin_registration
# 'testcenteruser': testcenteruser,
} }
return render_to_response('dashboard.html', context) return render_to_response('dashboard.html', context)
...@@ -657,11 +654,12 @@ def create_test_registration(request, post_override=None): ...@@ -657,11 +654,12 @@ def create_test_registration(request, post_override=None):
try: try:
testcenter_user = TestCenterUser.objects.get(user=user) testcenter_user = TestCenterUser.objects.get(user=user)
needs_updating = testcenter_user.needs_update(post_vars)
except TestCenterUser.DoesNotExist: except TestCenterUser.DoesNotExist:
# do additional initialization here: # do additional initialization here:
testcenter_user = TestCenterUser.create(user) testcenter_user = TestCenterUser.create(user)
needs_updating = True
needs_updating = testcenter_user.needs_update(post_vars)
# perform validation: # perform validation:
if needs_updating: if needs_updating:
...@@ -692,20 +690,28 @@ def create_test_registration(request, post_override=None): ...@@ -692,20 +690,28 @@ def create_test_registration(request, post_override=None):
# right now. # right now.
else: else:
accommodation_request = post_vars.get('accommodations','') accommodation_request = post_vars.get('accommodation_request','')
registration = TestCenterRegistration.create(testcenter_user, course_id, exam_info, accommodation_request) registration = TestCenterRegistration.create(testcenter_user, course_id, exam_info, accommodation_request)
needs_saving = True needs_saving = True
# TODO: add validation of registration. (Mainly whether an accommodation request is too long.)
if needs_saving: if needs_saving:
registration.save() # do validation of registration. (Mainly whether an accommodation request is too long.)
form = TestCenterRegistrationForm(instance=registration, data=post_vars)
if form.is_valid():
form.update_and_save()
else:
response_data = {'success': False}
# return a list of errors...
response_data['field_errors'] = form.errors
response_data['non_field_errors'] = form.non_field_errors()
return HttpResponse(json.dumps(response_data), mimetype="application/json")
# only do the following if there is accommodation text to send, # only do the following if there is accommodation text to send,
# and a destination to which to send it. # and a destination to which to send it.
# TODO: still need to create the accommodation email templates # TODO: still need to create the accommodation email templates
if 'accommodations' in post_vars and settings.MITX_FEATURES.get('ACCOMMODATION_EMAIL'): if 'accommodation_request' in post_vars and settings.MITX_FEATURES.get('ACCOMMODATION_EMAIL'):
d = {'accommodations': post_vars['accommodations'] } d = {'accommodation_request': post_vars['accommodation_request'] }
# composes accommodation email # composes accommodation email
subject = render_to_string('emails/accommodation_email_subject.txt', d) subject = render_to_string('emails/accommodation_email_subject.txt', d)
......
...@@ -247,7 +247,7 @@ ...@@ -247,7 +247,7 @@
<div class="message message-status is-shown exam-schedule"> <div class="message message-status is-shown exam-schedule">
<!-- TODO: pull Pearson destination out into a Setting --> <!-- TODO: pull Pearson destination out into a Setting -->
<a href="https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX" class="exam-button">Schedule Pearson exam</a> <a href="https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX" class="exam-button">Schedule Pearson exam</a>
<p class="exam-registration-number"><a href="${testcenter_register_target}" id="exam_register_link">Registration</a> number: <strong>edx00015879548</strong></p> <p class="exam-registration-number"><a href="${testcenter_register_target}" id="exam_register_link">Registration</a> number: <strong>${registrations[0].client_authorization_id}</strong></p>
<p class="message-copy">Write this down! You’ll need it to schedule your exam.</p> <p class="message-copy">Write this down! You’ll need it to schedule your exam.</p>
</div> </div>
% endif % endif
......
...@@ -68,17 +68,6 @@ ...@@ -68,17 +68,6 @@
$("label").removeClass("is-focused"); $("label").removeClass("is-focused");
}); });
$(document).delegate('#testcenter_register_form', 'ajax:success', function(data, json, xhr) {
if(json.success) {
location.href="${reverse('dashboard')}";
} else {
if($('#testcenter_register_error').length == 0) {
$('#testcenter_register_form').prepend('<div id="testcenter_register_error" class="modal-form-error"></div>');
}
$('#testcenter_register_error').text(json.field_errors).stop().css("display", "block");
}
});
})(this) })(this)
</script> </script>
</%block> </%block>
...@@ -262,9 +251,9 @@ ...@@ -262,9 +251,9 @@
</li> </li>
% endif % endif
% else: % else:
<li class="field"> <li data-field="accommodation_request" class="field">
<label for="accommodations">Accommodations Requested</label> <label for="accommodations">Accommodations Requested</label>
<textarea class="long" id="accommodations" name="accommodations" value="" placeholder=""></textarea> <textarea class="long" id="accommodations" name="accommodation_request" value="" placeholder=""></textarea>
</li> </li>
% endif % endif
</ol> </ol>
...@@ -290,7 +279,7 @@ ...@@ -290,7 +279,7 @@
<% regstatus = "Registration approved by Pearson" %> <% regstatus = "Registration approved by Pearson" %>
<div class="message message-status registration-accepted is-shown"> <div class="message message-status registration-accepted is-shown">
<p class="registration-status"><span class="label">Registration Status: </span><span class="value">${regstatus}</span></p> <p class="registration-status"><span class="label">Registration Status: </span><span class="value">${regstatus}</span></p>
<p class="registration-number"><span class="label">Registration number: </span> <span class="value">edx00015879548</span></p> <p class="registration-number"><span class="label">Registration number: </span> <span class="value">${registration.client_authorization_id}</span></p>
<p class="message-copy">Write this down! You’ll need it to schedule your exam.</p> <p class="message-copy">Write this down! You’ll need it to schedule your exam.</p>
<a href="https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX" class="button exam-button">Schedule Pearson exam</a> <a href="https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX" class="button exam-button">Schedule Pearson exam</a>
</div> </div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment