Skip to content
Snippets Groups Projects
Commit caaf351e authored by Michael Terry's avatar Michael Terry Committed by Diana Huang
Browse files

Fix visible dates sent to Credentials

If we have a future available_date, send that to Credentials rather
than sending the modified date.

LEARNER-5995
parent d9e84129
No related merge requests found
......@@ -95,13 +95,17 @@ def can_show_certificate_available_date_field(course):
return _enabled_and_instructor_paced(course)
def display_date_for_certificate(course, certificate):
if (
auto_certificate_generation_enabled() and
not course.self_paced and
course.certificate_available_date and
course.certificate_available_date < datetime.now(UTC)
):
def _course_uses_available_date(course):
return can_show_certificate_available_date_field(course) and course.certificate_available_date
def available_date_for_certificate(course, certificate):
if _course_uses_available_date(course):
return course.certificate_available_date
return certificate.modified_date
def display_date_for_certificate(course, certificate):
if _course_uses_available_date(course) and course.certificate_available_date < datetime.now(UTC):
return course.certificate_available_date
return certificate.modified_date
......@@ -121,3 +121,46 @@ class CertificatesApiTestCase(TestCase):
self.certificate.status = certificate_status
self.assertEqual(expected_value, api.is_certificate_valid(self.certificate))
@ddt.data(
(CourseMode.VERIFIED, CertificateStatuses.downloadable, True),
(CourseMode.VERIFIED, CertificateStatuses.notpassing, False),
(CourseMode.AUDIT, CertificateStatuses.downloadable, False)
)
@ddt.unpack
def test_available_date(self, enrollment_mode, certificate_status, expected_value):
self.enrollment.mode = enrollment_mode
self.enrollment.save()
self.certificate.mode = CourseMode.VERIFIED
self.certificate.status = certificate_status
self.assertEqual(expected_value, api.is_certificate_valid(self.certificate))
@ddt.data(
(True, True, False), # feature enabled and self-paced should return False
(True, False, True), # feature enabled and instructor-paced should return True
(False, True, False), # feature not enabled and self-paced should return False
(False, False, False), # feature not enabled and instructor-paced should return False
)
@ddt.unpack
def test_available_vs_display_date(
self, feature_enabled, is_self_paced, uses_avail_date
):
self.course.self_paced = is_self_paced
with configure_waffle_namespace(feature_enabled):
maybe_avail = self.course.certificate_available_date if uses_avail_date else self.certificate.modified_date
# With no available_date set, both return modified_date
self.assertEqual(self.certificate.modified_date, api.available_date_for_certificate(self.course))
self.assertEqual(self.certificate.modified_date, api.display_date_for_certificate(self.course))
# With an available date set in the past, both return the available date (if configured)
self.course.certificate_available_date = datetime(2017, 2, 1, tzinfo=pytz.UTC)
self.assertEqual(maybe_avail, api.available_date_for_certificate(self.course))
self.assertEqual(maybe_avail, api.display_date_for_certificate(self.course))
# With a future available date, they each return a different date
self.course.certificate_available_date = datetime.max
self.assertEqual(maybe_avail, api.available_date_for_certificate(self.course))
self.assertEqual(self.certificate.modified_date, api.display_date_for_certificate(self.course))
......@@ -12,7 +12,7 @@ from opaque_keys.edx.keys import CourseKey
from course_modes.models import CourseMode
from lms.djangoapps.certificates.models import GeneratedCertificate
from openedx.core.djangoapps.certificates.api import display_date_for_certificate
from openedx.core.djangoapps.certificates.api import available_date_for_certificate
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.credentials.models import CredentialsApiConfig
from openedx.core.djangoapps.credentials.utils import get_credentials, get_credentials_api_client
......@@ -301,7 +301,7 @@ def award_course_certificate(self, username, course_run_key):
# FIXME This may result in visible dates that do not update alongside the Course Overview if that changes
# This is a known limitation of this implementation and was chosen to reduce the amount of replication,
# endpoints, celery tasks, and jenkins jobs that needed to be written for this functionality
visible_date = display_date_for_certificate(course_overview, certificate)
visible_date = available_date_for_certificate(course_overview, certificate)
post_course_certificate(credentials_client, username, certificate, visible_date)
LOGGER.info('Awarded certificate for course %s to user %s', course_key, username)
......
......@@ -414,8 +414,10 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
def setUp(self):
super(AwardCourseCertificatesTestCase, self).setUp()
self.available_date = datetime.datetime.max
self.course = CourseOverviewFactory.create(
self_paced=True # Any option to allow the certificate to be viewable for the course
self_paced=True, # Any option to allow the certificate to be viewable for the course
certificate_available_date=self.available_date,
)
self.student = UserFactory.create(username='test-student')
# Instantiate the Certificate first so that the config doesn't execute issuance
......@@ -440,6 +442,7 @@ class AwardCourseCertificatesTestCase(CredentialsApiConfigMixin, TestCase):
call_args, _ = mock_post_course_certificate.call_args
self.assertEqual(call_args[1], self.student.username)
self.assertEqual(call_args[2], self.certificate)
self.assertEqual(call_args[3], self.available_date)
def test_award_course_cert_not_called_if_disabled(self, mock_post_course_certificate):
"""
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment