Skip to content
Snippets Groups Projects
Commit da94aca5 authored by zubair-arbi's avatar zubair-arbi
Browse files

add location_id field for the Reverification XBlock in VerificationStatus model

ECOM-1477
parent 5a1d180f
No related merge requests found
# -*- 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 ...@@ -13,34 +13,32 @@ from email.utils import formatdate
import functools import functools
import json import json
import logging 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 pytz
import requests import requests
import uuid
from django.conf import settings 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.core.urlresolvers import reverse
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.utils.translation import ugettext as _, ugettext_lazy
from django.utils.translation import ugettext as _
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.models import StatusModel
from model_utils import Choices from model_utils import Choices
from reverification.models import MidcourseReverificationWindow
from verify_student.ssencrypt import ( from verify_student.ssencrypt import (
random_aes_key, encrypt_and_encode, random_aes_key, encrypt_and_encode,
generate_signed_message, rsa_encrypt 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__) log = logging.getLogger(__name__)
from config_models.models import ConfigurationModel
def generateUUID(): # pylint: disable=invalid-name def generateUUID(): # pylint: disable=invalid-name
""" Utility function; generates UUIDs """ """ Utility function; generates UUIDs """
...@@ -1018,21 +1016,30 @@ class VerificationStatus(models.Model): ...@@ -1018,21 +1016,30 @@ class VerificationStatus(models.Model):
response = models.TextField(null=True, blank=True) response = models.TextField(null=True, blank=True)
error = 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 class Meta(object): # pylint: disable=missing-docstring
get_latest_by = "timestamp" get_latest_by = "timestamp"
@classmethod @classmethod
def add_verification_status(cls, checkpoint, user, status): def add_verification_status(cls, checkpoint, user, status, location_id=''):
""" Create new verification status object """ Create new verification status object
Arguments: Arguments:
checkpoint(VerificationCheckpoint): VerificationCheckpoint object checkpoint(VerificationCheckpoint): VerificationCheckpoint object
user(User): user object user(User): user object
status(str): String representing the status from VERIFICATION_STATUS_CHOICES status(str): String representing the status from VERIFICATION_STATUS_CHOICES
location_id(str): Usage key of Reverification XBlock
Returns: Returns:
None None
""" """
cls.objects.create(checkpoint=checkpoint, user=user, status=status) cls.objects.create(checkpoint=checkpoint, user=user, status=status, location_id=location_id)
@classmethod @classmethod
def add_status_from_checkpoints(cls, checkpoints, user, status): def add_status_from_checkpoints(cls, checkpoints, user, status):
...@@ -1046,7 +1053,14 @@ class VerificationStatus(models.Model): ...@@ -1046,7 +1053,14 @@ class VerificationStatus(models.Model):
None None
""" """
for checkpoint in checkpoints: 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): class InCourseReverificationConfiguration(ConfigurationModel):
......
...@@ -675,7 +675,7 @@ class VerificationCheckpointTest(ModuleStoreTestCase): ...@@ -675,7 +675,7 @@ class VerificationCheckpointTest(ModuleStoreTestCase):
@ddt.ddt @ddt.ddt
class VerificationStatusTest(ModuleStoreTestCase): class VerificationStatusTest(ModuleStoreTestCase):
"""Tests for the VerificationStatus model. """ """ Tests for the VerificationStatus model. """
def setUp(self): def setUp(self):
super(VerificationStatusTest, self).setUp() super(VerificationStatusTest, self).setUp()
...@@ -683,33 +683,70 @@ class VerificationStatusTest(ModuleStoreTestCase): ...@@ -683,33 +683,70 @@ class VerificationStatusTest(ModuleStoreTestCase):
self.course = CourseFactory.create() self.course = CourseFactory.create()
self.check_point1 = VerificationCheckpoint.objects.create(course_id=self.course.id, checkpoint_name="midterm") 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.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") @ddt.data('submitted', "approved", "denied", "error")
def test_add_verification_status(self, status): def test_add_verification_status(self, status):
"""adding verfication status using the class method.""" """ Adding verification status using the class method. """
# adding verification status # 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 # getting the status from db
result = VerificationStatus.objects.filter(checkpoint=self.check_point1)[0] result = VerificationStatus.objects.filter(checkpoint=self.check_point1)[0]
self.assertEqual(result.status, status) self.assertEqual(result.status, status)
self.assertEqual(result.user, self.user) 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): 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( VerificationStatus.add_status_from_checkpoints(
checkpoints=[self.check_point1, self.check_point2], user=self.user, status=status checkpoints=[self.check_point1, self.check_point2], user=self.user, status=status
) )
# getting the status from db. # test that verification status entries with new status have been added
result = VerificationStatus.objects.filter(user=self.user) # for both checkpoints and all entries have related 'location_id'.
self.assertEqual(len(result), len([self.check_point1.checkpoint_name, self.check_point2.checkpoint_name])) result = VerificationStatus.objects.filter(user=self.user, checkpoint=self.check_point1)
self.assertEqual(result[0].checkpoint.checkpoint_name, self.check_point1.checkpoint_name) self.assertEqual(len(result), len(self.check_point1.checkpoint_status.all()))
self.assertEqual(result[1].checkpoint.checkpoint_name, self.check_point2.checkpoint_name) 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): class SkippedReverificationTest(ModuleStoreTestCase):
......
...@@ -1244,7 +1244,7 @@ class InCourseReverifyView(View): ...@@ -1244,7 +1244,7 @@ class InCourseReverifyView(View):
request.user, request.POST['face_image'], init_verification.photo_id_key request.user, request.POST['face_image'], init_verification.photo_id_key
) )
checkpoint.add_verification_attempt(attempt) 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 # emit the reverification event
self._track_reverification_events( self._track_reverification_events(
......
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