Commit c183831b by Will Daly

Merge pull request #6423 from edx/will/ecom-864

Hide verification messaging if the user has an active verification
parents 0ac14dce 01814c39
......@@ -163,14 +163,20 @@ def check_verify_status_by_course(user, course_enrollment_pairs, all_course_mode
* status (str): One of the enumerated status codes.
* days_until_deadline (int): Number of days until the verification deadline.
* verification_good_until (str): Date string for the verification expiration date.
"""
"""
status_by_course = {}
# Retrieve all verifications for the user, sorted in descending
# order by submission datetime
verifications = SoftwareSecurePhotoVerification.objects.filter(user=user)
# Check whether the user has an active or pending verification attempt
# To avoid another database hit, we re-use the queryset we have already retrieved.
has_active_or_pending = SoftwareSecurePhotoVerification.user_has_valid_or_pending(
user, queryset=verifications
)
for course, enrollment in course_enrollment_pairs:
# Get the verified mode (if any) for this course
......@@ -210,7 +216,13 @@ def check_verify_status_by_course(user, course_enrollment_pairs, all_course_mode
)
if status is None and not submitted:
if deadline is None or deadline > datetime.now(UTC):
status = VERIFY_STATUS_NEED_TO_VERIFY
# If a user already has an active or pending verification,
# but it will expire by the deadline, the we do NOT show the
# verification message. This is because we don't currently
# allow users to resubmit an attempt before their current
# attempt expires.
if not has_active_or_pending:
status = VERIFY_STATUS_NEED_TO_VERIFY
else:
status = VERIFY_STATUS_MISSED_DEADLINE
......
......@@ -199,6 +199,26 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
# messaging relating to verification
self._assert_course_verification_status(None)
def test_verification_will_expire_by_deadline(self):
# Expiration date in the future
self._setup_mode_and_enrollment(self.FUTURE, "verified")
# Create a verification attempt that:
# 1) Is current (submitted in the last year)
# 2) Will expire by the deadline for the course
attempt = SoftwareSecurePhotoVerification.objects.create(user=self.user)
attempt.mark_ready()
attempt.submit()
# This attempt will expire tomorrow, before the course deadline
attempt.created_at = attempt.created_at - timedelta(days=364)
attempt.save()
# Expect that the "verify now" message is hidden
# (since the user isn't allowed to submit another attempt while
# a verification is active).
self._assert_course_verification_status(None)
def _setup_mode_and_enrollment(self, deadline, enrollment_mode):
"""Create a course mode and enrollment.
......@@ -227,9 +247,12 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
}
NOTIFICATION_MESSAGES = {
VERIFY_STATUS_NEED_TO_VERIFY: "You still need to verify for this course.",
VERIFY_STATUS_SUBMITTED: "Thanks for your patience as we process your request.",
VERIFY_STATUS_APPROVED: "You have already verified your ID!",
VERIFY_STATUS_NEED_TO_VERIFY: [
"You still need to verify for this course.",
"Verification not yet complete"
],
VERIFY_STATUS_SUBMITTED: ["Thanks for your patience as we process your request."],
VERIFY_STATUS_APPROVED: ["You have already verified your ID!"],
}
def _assert_course_verification_status(self, status):
......@@ -254,7 +277,25 @@ class TestCourseVerificationStatus(UrlResetMixin, ModuleStoreTestCase):
# Verify that the correct copy is rendered on the dashboard
if status is not None:
if status in self.NOTIFICATION_MESSAGES:
self.assertContains(response, self.NOTIFICATION_MESSAGES[status])
# Different states might have different messaging
# so in some cases we check several possibilities
# and fail if none of these are found.
found_msg = False
for message in self.NOTIFICATION_MESSAGES[status]:
if message in response.content:
found_msg = True
break
fail_msg = "Could not find any of these messages: {expected}".format(
expected=self.NOTIFICATION_MESSAGES[status]
)
self.assertTrue(found_msg, msg=fail_msg)
else:
for msg in self.NOTIFICATION_MESSAGES.values():
# Combine all possible messages into a single list
all_messages = []
for msg_group in self.NOTIFICATION_MESSAGES.values():
all_messages.extend(msg_group)
# Verify that none of the messages are displayed
for msg in all_messages:
self.assertNotContains(response, msg)
......@@ -211,7 +211,7 @@ class PhotoVerification(StatusModel):
).exists()
@classmethod
def user_has_valid_or_pending(cls, user, earliest_allowed_date=None, window=None):
def user_has_valid_or_pending(cls, user, earliest_allowed_date=None, window=None, queryset=None):
"""
Return whether the user has a complete verification attempt that is or
*might* be good. This means that it's approved, been submitted, or would
......@@ -222,15 +222,21 @@ class PhotoVerification(StatusModel):
If window=None, this will check for the user's *initial* verification. If
window is anything else, this will check for the reverification associated
with that window.
If a queryset is provided, that will be used instead of hitting the database.
"""
valid_statuses = ['submitted', 'approved']
if not window:
valid_statuses.append('must_retry')
return cls.objects.filter(
user=user,
if queryset is None:
queryset = cls.objects.filter(user=user)
return queryset.filter(
status__in=valid_statuses,
created_at__gte=(earliest_allowed_date
or cls._earliest_allowed_date()),
created_at__gte=(
earliest_allowed_date
or cls._earliest_allowed_date()
),
window=window,
).exists()
......
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