Commit da94aca5 by zubair-arbi

add location_id field for the Reverification XBlock in VerificationStatus model

ECOM-1477
parent 5a1d180f
# -*- coding: utf-8 -*-
from south.utils import datetime_utils as datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'VerificationStatus.location_id'
db.add_column('verify_student_verificationstatus', 'location_id',
self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True),
keep_default=False)
def backwards(self, orm):
# Deleting field 'VerificationStatus.location_id'
db.delete_column('verify_student_verificationstatus', 'location_id')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'reverification.midcoursereverificationwindow': {
'Meta': {'object_name': 'MidcourseReverificationWindow'},
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'end_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'start_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'})
},
'verify_student.incoursereverificationconfiguration': {
'Meta': {'object_name': 'InCourseReverificationConfiguration'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'verify_student.skippedreverification': {
'Meta': {'unique_together': "(('user', 'course_id'),)", 'object_name': 'SkippedReverification'},
'checkpoint': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'skipped_checkpoint'", 'to': "orm['verify_student.VerificationCheckpoint']"}),
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'verify_student.softwaresecurephotoverification': {
'Meta': {'ordering': "['-created_at']", 'object_name': 'SoftwareSecurePhotoVerification'},
'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
'display': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'db_index': 'True'}),
'error_code': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'error_msg': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'face_image_url': ('django.db.models.fields.URLField', [], {'max_length': '255', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'photo_id_image_url': ('django.db.models.fields.URLField', [], {'max_length': '255', 'blank': 'True'}),
'photo_id_key': ('django.db.models.fields.TextField', [], {'max_length': '1024'}),
'receipt_id': ('django.db.models.fields.CharField', [], {'default': "'9997c000-3299-4097-a2cf-9ab35f9efdb5'", 'max_length': '255', 'db_index': 'True'}),
'reviewing_service': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'reviewing_user': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'related_name': "'photo_verifications_reviewed'", 'null': 'True', 'to': "orm['auth.User']"}),
'status': ('model_utils.fields.StatusField', [], {'default': "'created'", 'max_length': '100', u'no_check_for_status': 'True'}),
'status_changed': ('model_utils.fields.MonitorField', [], {'default': 'datetime.datetime.now', u'monitor': "u'status'"}),
'submitted_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'db_index': 'True'}),
'updated_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'window': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['reverification.MidcourseReverificationWindow']", 'null': 'True'})
},
'verify_student.verificationcheckpoint': {
'Meta': {'unique_together': "(('course_id', 'checkpoint_name'),)", 'object_name': 'VerificationCheckpoint'},
'checkpoint_name': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'course_id': ('xmodule_django.models.CourseKeyField', [], {'max_length': '255', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'photo_verification': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['verify_student.SoftwareSecurePhotoVerification']", 'symmetrical': 'False'})
},
'verify_student.verificationstatus': {
'Meta': {'object_name': 'VerificationStatus'},
'checkpoint': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'checkpoint_status'", 'to': "orm['verify_student.VerificationCheckpoint']"}),
'error': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'location_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'response': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'max_length': '32', 'db_index': 'True'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
}
}
complete_apps = ['verify_student']
\ No newline at end of file
......@@ -13,34 +13,32 @@ from email.utils import formatdate
import functools
import json
import logging
import uuid
from boto.s3.connection import S3Connection
from boto.s3.key import Key
from django.core.exceptions import ObjectDoesNotExist
import pytz
import requests
import uuid
from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext as _, ugettext_lazy
from boto.s3.connection import S3Connection
from boto.s3.key import Key
from config_models.models import ConfigurationModel
from model_utils.models import StatusModel
from model_utils import Choices
from reverification.models import MidcourseReverificationWindow
from verify_student.ssencrypt import (
random_aes_key, encrypt_and_encode,
generate_signed_message, rsa_encrypt
)
from xmodule_django.models import CourseKeyField
from reverification.models import MidcourseReverificationWindow
from xmodule_django.models import CourseKeyField
log = logging.getLogger(__name__)
from config_models.models import ConfigurationModel
def generateUUID(): # pylint: disable=invalid-name
""" Utility function; generates UUIDs """
......@@ -1018,21 +1016,30 @@ class VerificationStatus(models.Model):
response = models.TextField(null=True, blank=True)
error = models.TextField(null=True, blank=True)
# This field is used to save location of Reverification module in courseware
location_id = models.CharField(
null=True,
blank=True,
max_length=255,
help_text=ugettext_lazy("Usage id of Reverification XBlock.")
)
class Meta(object): # pylint: disable=missing-docstring
get_latest_by = "timestamp"
@classmethod
def add_verification_status(cls, checkpoint, user, status):
def add_verification_status(cls, checkpoint, user, status, location_id=''):
""" Create new verification status object
Arguments:
checkpoint(VerificationCheckpoint): VerificationCheckpoint object
user(User): user object
status(str): String representing the status from VERIFICATION_STATUS_CHOICES
location_id(str): Usage key of Reverification XBlock
Returns:
None
"""
cls.objects.create(checkpoint=checkpoint, user=user, status=status)
cls.objects.create(checkpoint=checkpoint, user=user, status=status, location_id=location_id)
@classmethod
def add_status_from_checkpoints(cls, checkpoints, user, status):
......@@ -1046,7 +1053,14 @@ class VerificationStatus(models.Model):
None
"""
for checkpoint in checkpoints:
cls.objects.create(checkpoint=checkpoint, user=user, status=status)
# get 'location_id' from last entry (if it exists) and add it in
# new entry
try:
location_id = cls.objects.filter(checkpoint=checkpoint).latest().location_id
except cls.DoesNotExist:
location_id = ''
cls.objects.create(checkpoint=checkpoint, user=user, status=status, location_id=location_id)
class InCourseReverificationConfiguration(ConfigurationModel):
......
......@@ -675,7 +675,7 @@ class VerificationCheckpointTest(ModuleStoreTestCase):
@ddt.ddt
class VerificationStatusTest(ModuleStoreTestCase):
"""Tests for the VerificationStatus model. """
""" Tests for the VerificationStatus model. """
def setUp(self):
super(VerificationStatusTest, self).setUp()
......@@ -683,33 +683,70 @@ class VerificationStatusTest(ModuleStoreTestCase):
self.course = CourseFactory.create()
self.check_point1 = VerificationCheckpoint.objects.create(course_id=self.course.id, checkpoint_name="midterm")
self.check_point2 = VerificationCheckpoint.objects.create(course_id=self.course.id, checkpoint_name="final")
self.dummy_reverification_item_id_1 = 'i4x://{}/{}/edx-reverification-block/related_assessment_1'.format(
self.course.location.org,
self.course.location.course
)
self.dummy_reverification_item_id_2 = 'i4x://{}/{}/edx-reverification-block/related_assessment_2'.format(
self.course.location.org,
self.course.location.course
)
@ddt.data('submitted', "approved", "denied", "error")
def test_add_verification_status(self, status):
"""adding verfication status using the class method."""
""" Adding verification status using the class method. """
# adding verification status
VerificationStatus.add_verification_status(checkpoint=self.check_point1, user=self.user, status=status)
VerificationStatus.add_verification_status(
checkpoint=self.check_point1,
user=self.user,
status=status,
location_id=self.dummy_reverification_item_id_1
)
# getting the status from db
result = VerificationStatus.objects.filter(checkpoint=self.check_point1)[0]
self.assertEqual(result.status, status)
self.assertEqual(result.user, self.user)
@ddt.data('submitted', "approved", "denied", "error")
@ddt.data("approved", "denied", "error")
def test_add_status_from_checkpoints(self, status):
"""adding verfication status for checkpoints list."""
""" Adding verification status for checkpoints list after submitting sspv. """
# add initial verification status for checkpoints
initial_status = "submitted"
VerificationStatus.add_verification_status(
checkpoint=self.check_point1,
user=self.user,
status=initial_status,
location_id=self.dummy_reverification_item_id_1
)
VerificationStatus.add_verification_status(
checkpoint=self.check_point2,
user=self.user,
status=initial_status,
location_id=self.dummy_reverification_item_id_2
)
# adding verification status with multiple points
# now add verification status for multiple checkpoint points
VerificationStatus.add_status_from_checkpoints(
checkpoints=[self.check_point1, self.check_point2], user=self.user, status=status
)
# getting the status from db.
result = VerificationStatus.objects.filter(user=self.user)
self.assertEqual(len(result), len([self.check_point1.checkpoint_name, self.check_point2.checkpoint_name]))
self.assertEqual(result[0].checkpoint.checkpoint_name, self.check_point1.checkpoint_name)
self.assertEqual(result[1].checkpoint.checkpoint_name, self.check_point2.checkpoint_name)
# test that verification status entries with new status have been added
# for both checkpoints and all entries have related 'location_id'.
result = VerificationStatus.objects.filter(user=self.user, checkpoint=self.check_point1)
self.assertEqual(len(result), len(self.check_point1.checkpoint_status.all()))
self.assertEqual(
list(result.values_list('location_id', flat=True)),
list(self.check_point1.checkpoint_status.all().values_list('location_id', flat=True))
)
result = VerificationStatus.objects.filter(user=self.user, checkpoint=self.check_point2)
self.assertEqual(len(result), len(self.check_point2.checkpoint_status.all()))
self.assertEqual(
list(result.values_list('location_id', flat=True)),
list(self.check_point2.checkpoint_status.all().values_list('location_id', flat=True))
)
class SkippedReverificationTest(ModuleStoreTestCase):
......
......@@ -1244,7 +1244,7 @@ class InCourseReverifyView(View):
request.user, request.POST['face_image'], init_verification.photo_id_key
)
checkpoint.add_verification_attempt(attempt)
VerificationStatus.add_verification_status(checkpoint, user, "submitted")
VerificationStatus.add_verification_status(checkpoint, user, "submitted", usage_id)
# emit the reverification event
self._track_reverification_events(
......
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