Merge pull request #7849 from edx/zub/story/reverification-sevice-get-attempts-method
add 'get_attempts' method for 'ReverificationService'
This commit is contained in:
@@ -1,5 +1,31 @@
|
||||
from ratelimitbackend import admin
|
||||
from verify_student.models import SoftwareSecurePhotoVerification, InCourseReverificationConfiguration
|
||||
from verify_student.models import (
|
||||
SoftwareSecurePhotoVerification,
|
||||
InCourseReverificationConfiguration,
|
||||
VerificationStatus
|
||||
)
|
||||
|
||||
admin.site.register(SoftwareSecurePhotoVerification)
|
||||
|
||||
class SoftwareSecurePhotoVerificationAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Admin for the SoftwareSecurePhotoVerification table.
|
||||
"""
|
||||
list_display = ('id', 'user', 'status', 'receipt_id', 'submitted_at', 'updated_at')
|
||||
search_fields = (
|
||||
'receipt_id',
|
||||
)
|
||||
|
||||
|
||||
class VerificationStatusAdmin(admin.ModelAdmin):
|
||||
"""
|
||||
Admin for the VerificationStatus table.
|
||||
"""
|
||||
list_display = ('id', 'user', 'status', 'checkpoint', 'location_id')
|
||||
search_fields = (
|
||||
'checkpoint',
|
||||
)
|
||||
|
||||
|
||||
admin.site.register(SoftwareSecurePhotoVerification, SoftwareSecurePhotoVerificationAdmin)
|
||||
admin.site.register(InCourseReverificationConfiguration)
|
||||
admin.site.register(VerificationStatus, VerificationStatusAdmin)
|
||||
|
||||
@@ -1028,7 +1028,7 @@ class VerificationStatus(models.Model):
|
||||
get_latest_by = "timestamp"
|
||||
|
||||
@classmethod
|
||||
def add_verification_status(cls, checkpoint, user, status, location_id=''):
|
||||
def add_verification_status(cls, checkpoint, user, status, location_id=None):
|
||||
""" Create new verification status object
|
||||
|
||||
Arguments:
|
||||
@@ -1058,10 +1058,34 @@ class VerificationStatus(models.Model):
|
||||
try:
|
||||
location_id = cls.objects.filter(checkpoint=checkpoint).latest().location_id
|
||||
except cls.DoesNotExist:
|
||||
location_id = ''
|
||||
location_id = None
|
||||
|
||||
cls.objects.create(checkpoint=checkpoint, user=user, status=status, location_id=location_id)
|
||||
|
||||
@classmethod
|
||||
def get_user_attempts(cls, user_id, course_key, related_assessment, location_id):
|
||||
"""
|
||||
Get re-verification attempts against a user for a given 'checkpoint'
|
||||
and 'course_id'.
|
||||
|
||||
Arguments:
|
||||
user_id(str): User Id string
|
||||
course_key(str): A CourseKey of a course
|
||||
related_assessment(str): Verification checkpoint name
|
||||
location_id(str): Location of Reverification XBlock in courseware
|
||||
|
||||
Returns:
|
||||
count of re-verification attempts
|
||||
"""
|
||||
|
||||
return cls.objects.filter(
|
||||
user_id=user_id,
|
||||
checkpoint__course_id=course_key,
|
||||
checkpoint__checkpoint_name=related_assessment,
|
||||
location_id=location_id,
|
||||
status="submitted"
|
||||
).count()
|
||||
|
||||
|
||||
class InCourseReverificationConfiguration(ConfigurationModel):
|
||||
"""Configure in-course re-verification.
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
"""
|
||||
Implement the Reverification XBlock "reverification" server
|
||||
Implementation of "reverification" service to communicate with Reverification XBlock
|
||||
"""
|
||||
|
||||
import logging
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.urlresolvers import reverse
|
||||
from verify_student.models import VerificationCheckpoint, VerificationStatus, SkippedReverification
|
||||
from django.db import IntegrityError
|
||||
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from verify_student.models import VerificationCheckpoint, VerificationStatus, SkippedReverification
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ReverificationService(object):
|
||||
""" Service to implement the Reverification XBlock "reverification" service
|
||||
|
||||
"""
|
||||
Reverification XBlock service
|
||||
"""
|
||||
|
||||
def get_status(self, user_id, course_id, related_assessment):
|
||||
""" Check if the user has any verification attempt or has skipped the verification
|
||||
"""
|
||||
Get verification attempt status against a user for a given 'checkpoint'
|
||||
and 'course_id'.
|
||||
|
||||
Args:
|
||||
user_id(str): User Id string
|
||||
course_id(str): A string of course_id
|
||||
course_id(str): A string of course id
|
||||
related_assessment(str): Verification checkpoint name
|
||||
|
||||
Returns:
|
||||
@@ -44,10 +49,11 @@ class ReverificationService(object):
|
||||
return None
|
||||
|
||||
def start_verification(self, course_id, related_assessment, item_id):
|
||||
""" Get or create the verification checkpoint and return the re-verification link
|
||||
"""
|
||||
Create re-verification link against a verification checkpoint.
|
||||
|
||||
Args:
|
||||
course_id(str): A string of course_id
|
||||
course_id(str): A string of course id
|
||||
related_assessment(str): Verification checkpoint name
|
||||
|
||||
Returns:
|
||||
@@ -66,12 +72,13 @@ class ReverificationService(object):
|
||||
return re_verification_link
|
||||
|
||||
def skip_verification(self, checkpoint_name, user_id, course_id):
|
||||
"""Create the add verification attempt
|
||||
"""
|
||||
Add skipped verification attempt entry against a given 'checkpoint'
|
||||
|
||||
Args:
|
||||
course_id(str): A string of course_id
|
||||
user_id(str): User Id string
|
||||
checkpoint_name(str): Verification checkpoint name
|
||||
user_id(str): User Id string
|
||||
course_id(str): A string of course_id
|
||||
|
||||
Returns:
|
||||
None
|
||||
@@ -84,3 +91,20 @@ class ReverificationService(object):
|
||||
SkippedReverification.add_skipped_reverification_attempt(checkpoint, user_id, course_key)
|
||||
except IntegrityError:
|
||||
log.exception("Skipped attempt already exists for user %s: with course %s:", user_id, unicode(course_id))
|
||||
|
||||
def get_attempts(self, user_id, course_id, related_assessment, location_id):
|
||||
"""
|
||||
Get re-verification attempts against a user for a given 'checkpoint'
|
||||
and 'course_id'.
|
||||
|
||||
Args:
|
||||
user_id(str): User Id string
|
||||
course_id(str): A string of course id
|
||||
related_assessment(str): Verification checkpoint name
|
||||
location_id(str): Location of Reverification XBlock in courseware
|
||||
|
||||
Returns:
|
||||
Number of re-verification attempts of a user
|
||||
"""
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
return VerificationStatus.get_user_attempts(user_id, course_key, related_assessment, location_id)
|
||||
|
||||
@@ -1,24 +1,26 @@
|
||||
# encoding: utf-8
|
||||
"""
|
||||
Tests of reverify service.
|
||||
Tests of re-verification service.
|
||||
"""
|
||||
|
||||
import ddt
|
||||
|
||||
from course_modes.tests.factories import CourseModeFactory
|
||||
from student.tests.factories import UserFactory
|
||||
from verify_student.models import VerificationCheckpoint, VerificationStatus, SkippedReverification
|
||||
from verify_student.services import ReverificationService
|
||||
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from student.tests.factories import UserFactory
|
||||
from course_modes.tests.factories import CourseModeFactory
|
||||
from verify_student.services import ReverificationService
|
||||
from verify_student.models import VerificationCheckpoint, VerificationStatus, SkippedReverification
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
class TestReverifyService(ModuleStoreTestCase):
|
||||
class TestReverificationService(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for the re-verification service
|
||||
Tests for the re-verification service.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(TestReverifyService, self).setUp()
|
||||
super(TestReverificationService, self).setUp()
|
||||
|
||||
self.user = UserFactory.create(username="rusty", password="test")
|
||||
course = CourseFactory.create(org='Robot', number='999', display_name='Test Course')
|
||||
@@ -27,18 +29,18 @@ class TestReverifyService(ModuleStoreTestCase):
|
||||
mode_slug="verified",
|
||||
course_id=self.course_key,
|
||||
min_price=100,
|
||||
suggested_prices=''
|
||||
)
|
||||
self.item = ItemFactory.create(parent=course, category='chapter', display_name='Test Section')
|
||||
|
||||
@ddt.data("final_term", "mid_term")
|
||||
def test_start_verification(self, checkpoint_name):
|
||||
"""Testing start verification service. If checkpoint exists for specific course then returns the checkpoint
|
||||
otherwise created that checkpoint.
|
||||
"""
|
||||
|
||||
rev = ReverificationService()
|
||||
rev.start_verification(unicode(self.course_key), checkpoint_name, self.item.location)
|
||||
Test the 'start_verification' service method. If checkpoint exists for
|
||||
a specific course then return the checkpoint otherwise create that
|
||||
checkpoint.
|
||||
"""
|
||||
reverification_service = ReverificationService()
|
||||
reverification_service.start_verification(unicode(self.course_key), checkpoint_name, self.item.location)
|
||||
expected_url = (
|
||||
'/verify_student/reverify'
|
||||
'/{course_key}'
|
||||
@@ -47,36 +49,71 @@ class TestReverifyService(ModuleStoreTestCase):
|
||||
).format(course_key=unicode(self.course_key), checkpoint_name=checkpoint_name, usage_id=self.item.location)
|
||||
|
||||
self.assertEqual(
|
||||
expected_url, rev.start_verification(unicode(self.course_key), checkpoint_name, self.item.location)
|
||||
expected_url,
|
||||
reverification_service.start_verification(unicode(self.course_key), checkpoint_name, self.item.location)
|
||||
)
|
||||
|
||||
def test_get_status(self):
|
||||
""" Check if the user has any verification attempt for the checkpoint and course_id """
|
||||
|
||||
"""
|
||||
Test the verification statuses of a user for a given 'checkpoint' and
|
||||
'course_id'.
|
||||
"""
|
||||
checkpoint_name = 'final_term'
|
||||
rev = ReverificationService()
|
||||
self.assertIsNone(rev.get_status(self.user.id, unicode(self.course_key), checkpoint_name))
|
||||
reverification_service = ReverificationService()
|
||||
self.assertIsNone(reverification_service.get_status(self.user.id, unicode(self.course_key), checkpoint_name))
|
||||
|
||||
checkpoint_obj = VerificationCheckpoint.objects.create(
|
||||
course_id=unicode(self.course_key), checkpoint_name=checkpoint_name
|
||||
course_id=unicode(self.course_key),
|
||||
checkpoint_name=checkpoint_name
|
||||
)
|
||||
|
||||
VerificationStatus.objects.create(checkpoint=checkpoint_obj, user=self.user, status='submitted')
|
||||
self.assertEqual(rev.get_status(self.user.id, unicode(self.course_key), checkpoint_name), 'submitted')
|
||||
|
||||
def test_skip_verification(self):
|
||||
""" Adding the test skip verification attempt for the user """
|
||||
|
||||
checkpoint_name = 'final_term'
|
||||
rev = ReverificationService()
|
||||
|
||||
VerificationCheckpoint.objects.create(
|
||||
course_id=unicode(self.course_key), checkpoint_name=checkpoint_name
|
||||
self.assertEqual(
|
||||
reverification_service.get_status(self.user.id, unicode(self.course_key), checkpoint_name),
|
||||
'submitted'
|
||||
)
|
||||
|
||||
rev.skip_verification(checkpoint_name, self.user.id, unicode(self.course_key))
|
||||
VerificationStatus.objects.create(checkpoint=checkpoint_obj, user=self.user, status='submitted')
|
||||
self.assertEqual(
|
||||
reverification_service.get_status(self.user.id, unicode(self.course_key), checkpoint_name),
|
||||
'submitted'
|
||||
)
|
||||
|
||||
def test_skip_verification(self):
|
||||
"""
|
||||
Adding the test skip verification attempt for the user
|
||||
"""
|
||||
checkpoint_name = 'final_term'
|
||||
reverification_service = ReverificationService()
|
||||
VerificationCheckpoint.objects.create(
|
||||
course_id=unicode(self.course_key),
|
||||
checkpoint_name=checkpoint_name
|
||||
)
|
||||
|
||||
reverification_service.skip_verification(checkpoint_name, self.user.id, unicode(self.course_key))
|
||||
self.assertEqual(1, SkippedReverification.objects.filter(user=self.user, course_id=self.course_key).count())
|
||||
|
||||
rev.skip_verification(checkpoint_name, self.user.id, unicode(self.course_key))
|
||||
|
||||
reverification_service.skip_verification(checkpoint_name, self.user.id, unicode(self.course_key))
|
||||
self.assertEqual(1, SkippedReverification.objects.filter(user=self.user, course_id=self.course_key).count())
|
||||
|
||||
def test_get_attempts(self):
|
||||
"""
|
||||
Check verification attempts count against a user for a given
|
||||
'checkpoint' and 'course_id'.
|
||||
"""
|
||||
checkpoint_name = 'final_term'
|
||||
reverification_service = ReverificationService()
|
||||
course_id = unicode(self.course_key)
|
||||
self.assertEqual(
|
||||
reverification_service.get_attempts(self.user.id, course_id, checkpoint_name, location_id=None),
|
||||
0
|
||||
)
|
||||
|
||||
# now create a checkpoint and add user's entry against it then test
|
||||
# that the 'get_attempts' service method returns count accordingly
|
||||
checkpoint_obj = VerificationCheckpoint.objects.create(course_id=course_id, checkpoint_name=checkpoint_name)
|
||||
VerificationStatus.objects.create(checkpoint=checkpoint_obj, user=self.user, status='submitted')
|
||||
self.assertEqual(
|
||||
reverification_service.get_attempts(self.user.id, course_id, checkpoint_name, location_id=None),
|
||||
1
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user