diff --git a/common/djangoapps/student/helpers.py b/common/djangoapps/student/helpers.py index 6e0261aa0b..40116dd27b 100644 --- a/common/djangoapps/student/helpers.py +++ b/common/djangoapps/student/helpers.py @@ -106,6 +106,8 @@ def check_verify_status_by_course(user, course_enrollment_pairs, all_course_mode user, queryset=verifications ) + recent_verification_datetime = None + for course, enrollment in course_enrollment_pairs: # Get the verified mode (if any) for this course @@ -122,8 +124,17 @@ def check_verify_status_by_course(user, course_enrollment_pairs, all_course_mode # verification status. if verified_mode is not None and enrollment.mode in CourseMode.VERIFIED_MODES: deadline = verified_mode.expiration_datetime + relevant_verification = SoftwareSecurePhotoVerification.verification_for_datetime(deadline, verifications) + # Picking the max verification datetime on each iteration only with approved status + if relevant_verification is not None and relevant_verification.status == "approved": + recent_verification_datetime = max( + recent_verification_datetime if recent_verification_datetime is not None + else relevant_verification.expiration_datetime, + relevant_verification.expiration_datetime + ) + # By default, don't show any status related to verification status = None @@ -173,19 +184,18 @@ def check_verify_status_by_course(user, course_enrollment_pairs, all_course_mode # Otherwise, leave the course out of the dictionary. if status is not None: days_until_deadline = None - verification_good_until = None now = datetime.now(UTC) if deadline is not None and deadline > now: days_until_deadline = (deadline - now).days - if relevant_verification is not None: - verification_good_until = relevant_verification.expiration_datetime.strftime("%m/%d/%Y") - status_by_course[course.id] = { 'status': status, - 'days_until_deadline': days_until_deadline, - 'verification_good_until': verification_good_until + 'days_until_deadline': days_until_deadline } + if recent_verification_datetime: + for key, value in status_by_course.iteritems(): # pylint: disable=unused-variable + status_by_course[key]['verification_good_until'] = recent_verification_datetime.strftime("%m/%d/%Y") + return status_by_course diff --git a/common/djangoapps/student/tests/test_verification_status.py b/common/djangoapps/student/tests/test_verification_status.py index c4473f11dc..75c0aaf9da 100644 --- a/common/djangoapps/student/tests/test_verification_status.py +++ b/common/djangoapps/student/tests/test_verification_status.py @@ -7,6 +7,7 @@ from mock import patch from pytz import UTC from django.core.urlresolvers import reverse from django.conf import settings +from reverification.tests.factories import MidcourseReverificationWindowFactory from student.helpers import ( VERIFY_STATUS_NEED_TO_VERIFY, @@ -224,6 +225,56 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase): # Expect that the user's displayed enrollment mode is verified. self._assert_course_verification_status(VERIFY_STATUS_APPROVED) + def test_with_two_verifications(self): + # checking if a user has two verification and but most recent verification course deadline is expired + + self._setup_mode_and_enrollment(self.FUTURE, "verified") + + # The student has an approved verification + attempt = SoftwareSecurePhotoVerification.objects.create(user=self.user) + attempt.mark_ready() + attempt.submit() + attempt.approve() + # Making created at to previous date to differentiate with 2nd attempt. + attempt.created_at = datetime.now(UTC) - timedelta(days=1) + attempt.save() + + # Expect that the successfully verified message is shown + self._assert_course_verification_status(VERIFY_STATUS_APPROVED) + + # Check that the "verification good until" date is displayed + response = self.client.get(self.dashboard_url) + self.assertContains(response, attempt.expiration_datetime.strftime("%m/%d/%Y")) + + # Adding another verification with different course. + # Its created_at is greater than course deadline. + course2 = CourseFactory.create() + CourseModeFactory( + course_id=course2.id, + mode_slug="verified", + expiration_datetime=self.PAST + ) + CourseEnrollmentFactory( + course_id=course2.id, + user=self.user, + mode="verified" + ) + + window = MidcourseReverificationWindowFactory(course_id=course2.id) + # The student has an approved verification + attempt2 = SoftwareSecurePhotoVerification.objects.create(user=self.user) + attempt2.mark_ready() + attempt2.submit() + attempt2.approve() + attempt2.window = window + attempt2.save() + + # Mark the attemp2 as approved so its date will appear on dasboard. + self._assert_course_verification_status(VERIFY_STATUS_APPROVED) + response2 = self.client.get(self.dashboard_url) + self.assertContains(response2, attempt2.expiration_datetime.strftime("%m/%d/%Y")) + self.assertEqual(response2.content.count(attempt2.expiration_datetime.strftime("%m/%d/%Y")), 2) + def _setup_mode_and_enrollment(self, deadline, enrollment_mode): """Create a course mode and enrollment. diff --git a/lms/templates/dashboard/_dashboard_course_listing.html b/lms/templates/dashboard/_dashboard_course_listing.html index f9991f9362..95929ce331 100644 --- a/lms/templates/dashboard/_dashboard_course_listing.html +++ b/lms/templates/dashboard/_dashboard_course_listing.html @@ -277,7 +277,7 @@ from student.helpers import (
% elif verification_status['status'] == VERIFY_STATUS_APPROVED: