Commit ffd72c10 by Sofiya Semenova Committed by GitHub

Merge pull request #15705 from edx/ssemenova/ed-526

EDUCATOR-526 Update view certificate button
parents b8e48146 76f1df6b
......@@ -514,6 +514,7 @@ class DashboardTest(ModuleStoreTestCase):
expiration_datetime=datetime.now(pytz.UTC) - timedelta(days=1)
)
self.course.certificate_available_date = datetime.now(pytz.UTC) - timedelta(days=1)
CourseEnrollment.enroll(self.user, self.course.id, mode='honor')
self.course.start = datetime.now(pytz.UTC) - timedelta(days=2)
......
......@@ -93,7 +93,12 @@ def course_start_date_is_default(start, advertised_start):
return advertised_start is None and start == DEFAULT_START_DATE
def may_certify_for_course(certificates_display_behavior, certificates_show_before_end, has_ended):
def may_certify_for_course(
certificates_display_behavior,
certificates_show_before_end,
has_ended,
certificate_available_date
):
"""
Returns whether it is acceptable to show the student a certificate download
link for a course.
......@@ -105,12 +110,24 @@ def may_certify_for_course(certificates_display_behavior, certificates_show_befo
certificates_show_before_end (bool): whether user can download the
course's certificates before the course has ended.
has_ended (bool): Whether the course has ended.
certificate_available_date (datetime): the date the certificate is available on for the course.
"""
show_early = (
certificates_display_behavior in ('early_with_info', 'early_no_info')
or certificates_show_before_end
)
return show_early or has_ended
past_availability_date = (
certificate_available_date
and certificate_available_date < datetime.now(utc)
)
if show_early:
return True
if past_availability_date:
return True
if (certificate_available_date is None) and has_ended:
return True
return False
def sorting_score(start, advertised_start, announcement):
......
......@@ -1065,7 +1065,8 @@ class CourseDescriptor(CourseFields, SequenceDescriptor, LicenseMixin):
return course_metadata_utils.may_certify_for_course(
self.certificates_display_behavior,
self.certificates_show_before_end,
self.has_ended()
self.has_ended(),
self.certificate_available_date
)
def has_started(self):
......
......@@ -161,11 +161,14 @@ class CourseMetadataUtilsTestCase(TestCase):
TestScenario((DEFAULT_START_DATE, None), True),
]),
FunctionTest(may_certify_for_course, [
TestScenario(('early_with_info', True, True), True),
TestScenario(('early_no_info', False, False), True),
TestScenario(('end', True, False), True),
TestScenario(('end', False, True), True),
TestScenario(('end', False, False), False),
TestScenario(('early_with_info', True, True, test_datetime), True),
TestScenario(('early_no_info', False, False, test_datetime), True),
TestScenario(('end', True, False, test_datetime), True),
TestScenario(('end', False, True, test_datetime), True),
TestScenario(('end', False, False, _NEXT_WEEK), False),
TestScenario(('end', False, False, _LAST_WEEK), True),
TestScenario(('end', False, False, None), False),
TestScenario(('early_with_info', False, False, None), True),
]),
]
......
......@@ -4,6 +4,7 @@ from contextlib import contextmanager
from functools import wraps
import ddt
from datetime import datetime
from config_models.models import cache
from django.conf import settings
from django.core.urlresolvers import reverse
......@@ -92,7 +93,8 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
self.course = CourseFactory.create(
org='edx',
number='verified',
display_name='Verified Course'
display_name='Verified Course',
end=datetime.now()
)
self.request_factory = RequestFactory()
......
......@@ -1216,6 +1216,8 @@ class ProgressPageBaseTests(ModuleStoreTestCase):
self.course = CourseFactory.create(
start=datetime(2013, 9, 16, 7, 17, 28),
grade_cutoffs={u'çü†øƒƒ': 0.75, 'Pass': 0.5},
end=datetime.now(),
certificate_available_date=datetime.now(),
**options
)
......@@ -2052,6 +2054,7 @@ class GenerateUserCertTests(ModuleStoreTestCase):
self.course = CourseFactory.create(
org='edx',
number='verified',
end=datetime.now(),
display_name='Verified Course',
grade_cutoffs={'cutoff': 0.75, 'Pass': 0.5}
)
......
......@@ -112,7 +112,9 @@ log = logging.getLogger("edx.courseware")
# credit and verified modes.
REQUIREMENTS_DISPLAY_MODES = CourseMode.CREDIT_MODES + [CourseMode.VERIFIED]
CertData = namedtuple("CertData", ["cert_status", "title", "msg", "download_url", "cert_web_view_url"])
CertData = namedtuple(
"CertData", ["cert_status", "title", "msg", "download_url", "cert_web_view_url", "may_view_certificate"]
)
def user_groups(user):
......@@ -919,6 +921,7 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
Returns:
returns dict if course certificate is available else None.
"""
from lms.djangoapps.courseware.courses import get_course_by_id
if enrollment_mode == CourseMode.AUDIT:
return CertData(
......@@ -926,24 +929,28 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
_('Your enrollment: Audit track'),
_('You are enrolled in the audit track for this course. The audit track does not include a certificate.'),
download_url=None,
cert_web_view_url=None
cert_web_view_url=None,
may_view_certificate=None
)
show_generate_cert_btn = (
show_message = (
is_active and CourseMode.is_eligible_for_certificate(enrollment_mode)
and certs_api.cert_generation_enabled(course_key)
)
if not show_generate_cert_btn:
if not show_message:
return None
may_view_certificate = course_key and get_course_by_id(course_key).may_certify()
if certs_api.is_certificate_invalid(student, course_key):
return CertData(
CertificateStatuses.invalidated,
_('Your certificate has been invalidated'),
_('Please contact your course team if you have any questions.'),
download_url=None,
cert_web_view_url=None
cert_web_view_url=None,
may_view_certificate=None
)
cert_downloadable_status = certs_api.certificate_downloadable_status(student, course_key)
......@@ -957,7 +964,12 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
cert_web_view_url = certs_api.get_certificate_url(
course_id=course_key, uuid=cert_downloadable_status['uuid']
)
return CertData(cert_status, title, msg, download_url=None, cert_web_view_url=cert_web_view_url)
return CertData(cert_status,
title,
msg,
download_url=None,
cert_web_view_url=cert_web_view_url,
may_view_certificate=may_view_certificate)
else:
return CertData(
CertificateStatuses.generating,
......@@ -967,11 +979,17 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
"to it will appear here and on your Dashboard when it is ready."
),
download_url=None,
cert_web_view_url=None
cert_web_view_url=None,
may_view_certificate=None
)
return CertData(
cert_status, title, msg, download_url=cert_downloadable_status['download_url'], cert_web_view_url=None
cert_status,
title,
msg,
download_url=cert_downloadable_status['download_url'],
cert_web_view_url=None,
may_view_certificate=may_view_certificate
)
if cert_downloadable_status['is_generating']:
......@@ -983,7 +1001,8 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
"it will appear here and on your Dashboard when it is ready."
),
download_url=None,
cert_web_view_url=None
cert_web_view_url=None,
may_view_certificate=None
)
# If the learner is in verified modes and the student did not have
......@@ -1001,7 +1020,8 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
'verified identity.'
).format(platform_name=platform_name),
download_url=None,
cert_web_view_url=None
cert_web_view_url=None,
may_view_certificate=None
)
return CertData(
......@@ -1009,7 +1029,8 @@ def _get_cert_data(student, course, course_key, is_active, enrollment_mode):
_('Congratulations, you qualified for a certificate!'),
_('You can keep working for a higher grade, or request your certificate now.'),
download_url=None,
cert_web_view_url=None
cert_web_view_url=None,
may_view_certificate=may_view_certificate
)
......@@ -1355,7 +1376,7 @@ def _track_successful_certificate_generation(user_id, course_id): # pylint: dis
Track a successful certificate generation event.
Arguments:
user_id (str): The ID of the user generting the certificate.
user_id (str): The ID of the user generating the certificate.
course_id (CourseKey): Identifier for the course.
Returns:
None
......
......@@ -13,6 +13,7 @@ Test utilities for mobile API tests:
from datetime import timedelta
import ddt
import datetime
from django.conf import settings
from django.core.urlresolvers import reverse
from django.utils import timezone
......@@ -39,7 +40,10 @@ class MobileAPITestCase(ModuleStoreTestCase, APITestCase):
"""
def setUp(self):
super(MobileAPITestCase, self).setUp()
self.course = CourseFactory.create(mobile_available=True, static_asset_path="needed_for_split")
self.course = CourseFactory.create(
mobile_available=True,
static_asset_path="needed_for_split",
end=datetime.datetime.now())
self.user = UserFactory.create()
self.password = 'test'
self.username = self.user.username
......
......@@ -67,6 +67,7 @@ from django.utils.http import urlquote_plus
<h4 class="hd hd-4 title">${certificate_data.title}</h4>
<p class="copy">${certificate_data.msg}</p>
</div>
%if certificate_data.may_view_certificate:
<div class="msg-actions">
%if certificate_data.cert_web_view_url:
<a class="btn" href="${certificate_data.cert_web_view_url}" target="_blank">${_("View Certificate")} <span class="sr">${_("Opens in a new browser window")}</span></a>
......@@ -76,6 +77,7 @@ from django.utils.http import urlquote_plus
<button class="btn generate_certs" data-endpoint="${post_url}" id="btn_generate_cert">${_('Request Certificate')}</button>
%endif
</div>
%endif
</div>
</div>
%endif
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('course_overviews', '0013_courseoverview_language'),
]
operations = [
migrations.AddField(
model_name='courseoverview',
name='certificate_available_date',
field=models.DateTimeField(default=None, null=True),
),
]
......@@ -75,6 +75,7 @@ class CourseOverview(TimeStampedModel):
has_any_active_web_certificate = BooleanField(default=False)
cert_name_short = TextField()
cert_name_long = TextField()
certificate_available_date = DateTimeField(default=None, null=True)
# Grading
lowest_passing_grade = DecimalField(max_digits=5, decimal_places=2, null=True)
......@@ -172,6 +173,7 @@ class CourseOverview(TimeStampedModel):
course_overview.has_any_active_web_certificate = (get_active_web_certificate(course) is not None)
course_overview.cert_name_short = course.cert_name_short
course_overview.cert_name_long = course.cert_name_long
course_overview.certificate_available_date = course.certificate_available_date
course_overview.lowest_passing_grade = lowest_passing_grade
course_overview.end_of_course_survey_url = course.end_of_course_survey_url
......@@ -476,7 +478,8 @@ class CourseOverview(TimeStampedModel):
return course_metadata_utils.may_certify_for_course(
self.certificates_display_behavior,
self.certificates_show_before_end,
self.has_ended()
self.has_ended(),
self.certificate_available_date
)
@property
......
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