Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: removes deprecated v1 certificate behavior #35562

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,3 @@ class CourseSettingsSerializer(serializers.Serializer):
show_min_grade_warning = serializers.BooleanField()
sidebar_html_enabled = serializers.BooleanField()
upgrade_deadline = serializers.DateTimeField(allow_null=True)
use_v2_cert_display_settings = serializers.BooleanField()
2 changes: 0 additions & 2 deletions cms/djangoapps/contentstore/rest_api/v1/views/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ def get(self, request: Request, course_id: str):
"show_min_grade_warning": false,
"sidebar_html_enabled": true,
"upgrade_deadline": null,
"use_v2_cert_display_settings": false
}
```
"""
Expand All @@ -112,7 +111,6 @@ def get(self, request: Request, course_id: str):
'course_display_name_with_default': course_block.display_name_with_default,
'platform_name': settings.PLATFORM_NAME,
'licensing_enabled': settings.FEATURES.get("LICENSING", False),
'use_v2_cert_display_settings': settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS", False),
})

serializer = CourseSettingsSerializer(settings_context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ def test_course_settings_response(self):
"show_min_grade_warning": False,
"upgrade_deadline": None,
"licensing_enabled": False,
"use_v2_cert_display_settings": False,
}

self.assertEqual(response.status_code, status.HTTP_200_OK)
Expand Down
11 changes: 0 additions & 11 deletions cms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,17 +468,6 @@
# .. toggle_tickets: https://github.com/openedx/edx-platform/pull/26106
'ENABLE_HELP_LINK': True,

# .. toggle_name: FEATURES['ENABLE_V2_CERT_DISPLAY_SETTINGS']
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
# .. toggle_description: Whether to use the reimagined certificates_display_behavior and certificate_available_date
# .. settings. Will eventually become the default.
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2021-07-26
# .. toggle_target_removal_date: 2021-10-01
# .. toggle_tickets: 'https://openedx.atlassian.net/browse/MICROBA-1405'
'ENABLE_V2_CERT_DISPLAY_SETTINGS': False,

# .. toggle_name: FEATURES['ENABLE_INTEGRITY_SIGNATURE']
# .. toggle_implementation: DjangoSetting
# .. toggle_default: False
Expand Down
68 changes: 27 additions & 41 deletions cms/templates/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
${show_min_grade_warning | n, dump_js_escaped_json},
${can_show_certificate_available_date_field(context_course) | n, dump_js_escaped_json},
"${upgrade_deadline | n, js_escaped_string}",
${settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS") | n, dump_js_escaped_json}
);
});
</%block>
Expand Down Expand Up @@ -251,58 +250,45 @@ <h2 class="title-2">${_('Course Schedule')}</h2>
</li>
</ol>

<%
use_v2_cert_display_settings = settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS", False)
%>
% if can_show_certificate_available_date_field(context_course):
<ol class="list-input">
<li class="field-group field-group-certificate-available" id="certificate-available">
<div class="field date" id="field-certificates-display-behavior">
<label for="certificates-display-behavior">${_("Certificates Display Behavior")}</label>
% if use_v2_cert_display_settings:
<select id="certificates-display-behavior">
<option value="early_no_info">${_("Immediately upon passing")}</option>
<option value="end">${_("End date of course")}</option>
<option value="end_with_date">${_("A date after the course end date")}</option>
</select>
% else:
<input id="certificates-display-behavior" type="text">
% endif
<select id="certificates-display-behavior">
<option value="early_no_info">${_("Immediately upon passing")}</option>
<option value="end">${_("End date of course")}</option>
<option value="end_with_date">${_("A date after the course end date")}</option>
</select>
<span class="tip tip-stacked">${_("Certificates are awarded at the end of a course run")}</span>

% if use_v2_cert_display_settings:
<!-- Collapsible -->
<div class="collapsible">
<div id="certificate-display-behavior-collapsible-trigger" class="collapsible-trigger" role="button" tabindex="0" aria-expanded="false">
<span>
<span class="icon icon-inline fa fa-info-circle" aria-hidden="true"></span>
${_("Read more about this setting")}
</span>
<!-- Collapsible -->
<div class="collapsible">
<div id="certificate-display-behavior-collapsible-trigger" class="collapsible-trigger" role="button" tabindex="0" aria-expanded="false">
<span>
<span class="icon icon-inline fa fa-info-circle" aria-hidden="true"></span>
${_("Read more about this setting")}
</span>
</div>
<div id="certificate-display-behavior-collapsible-content" class="collapsible-content collapsed">
<p>${_("In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design)")}</p>
<div>
<div class="collapsible-description-heading">${_("Immediately upon passing")}</div>
<div class="collapsible-description-description">${_("Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.")}</div>
</div>
<div id="certificate-display-behavior-collapsible-content" class="collapsible-content collapsed">
<p>${_("In all configurations of this setting, certificates are generated for learners as soon as they achieve the passing threshold in the course (which can occur before a final assignment based on course design)")}</p>
<div>
<div class="collapsible-description-heading">${_("Immediately upon passing")}</div>
<div class="collapsible-description-description">${_("Learners can access their certificate as soon as they achieve a passing grade above the course grade threshold. Note: learners can achieve a passing grade before encountering all assignments in some course configurations.")}</div>
</div>
<div>
<div class="collapsible-description-heading">${_("On course end date")}</div>
<div class="collapsible-description-description">${_("Learners with passing grades can access their certificate once the end date of the course has elapsed.")}</div>
</div>
<div>
<div class="collapsible-description-heading">${_("A date after the course end date")}</div>
<div class="collapsible-description-description">${_("Learners with passing grades can access their certificate after the date that you set has elapsed.")}</div>
</div>
<div>
<div class="collapsible-description-heading">${_("On course end date")}</div>
<div class="collapsible-description-description">${_("Learners with passing grades can access their certificate once the end date of the course has elapsed.")}</div>
</div>
<div>
<div class="collapsible-description-heading">${_("A date after the course end date")}</div>
<div class="collapsible-description-description">${_("Learners with passing grades can access their certificate after the date that you set has elapsed.")}</div>
</div>
</div>
% endif
</div>
</div>

% if use_v2_cert_display_settings:
<div class="field date hidden" id="field-certificate-available-date" >
% else:
<div class="field date" id="field-certificate-available-date" >
% endif
<div class="field date hidden" id="field-certificate-available-date" >
<label for="certificate-available-date">${_("Certificates Available Date")}</label>
<input type="text" class="certificate-available-date date start datepicker" id="certificate-available-date" placeholder="MM/DD/YYYY" autocomplete="off" />
<span class="icon icon-inline fa fa-calendar-check-o datepicker-icon" aria-hidden="true"></span>
Expand Down
21 changes: 7 additions & 14 deletions common/djangoapps/student/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,21 +646,14 @@ def _is_certificate_earned_but_not_available(course_overview, status):
(bool): True if the user earned the certificate but it's hidden due to display behavior, else False

"""
if settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS"):
return (
not certificates_viewable_for_course(course_overview)
and CertificateStatuses.is_passing_status(status)
and course_overview.certificates_display_behavior in (
CertificatesDisplayBehaviors.END_WITH_DATE,
CertificatesDisplayBehaviors.END
)
)
else:
return (
not certificates_viewable_for_course(course_overview) and
CertificateStatuses.is_passing_status(status) and
course_overview.certificate_available_date
return (
not certificates_viewable_for_course(course_overview)
and CertificateStatuses.is_passing_status(status)
and course_overview.certificates_display_behavior in (
CertificatesDisplayBehaviors.END_WITH_DATE,
CertificatesDisplayBehaviors.END
)
)


def process_survey_link(survey_link, user):
Expand Down
15 changes: 4 additions & 11 deletions lms/djangoapps/certificates/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import logging
from datetime import datetime

from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
Expand Down Expand Up @@ -286,12 +285,9 @@ def certificate_downloadable_status(student, course_key):

course_overview = get_course_overview_or_none(course_key)

if settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS"):
display_behavior_is_valid = (
course_overview.certificates_display_behavior == CertificatesDisplayBehaviors.END_WITH_DATE
)
else:
display_behavior_is_valid = True
display_behavior_is_valid = (
course_overview.certificates_display_behavior == CertificatesDisplayBehaviors.END_WITH_DATE
)

if (
not certificates_viewable_for_course(course_overview)
Expand Down Expand Up @@ -837,10 +833,7 @@ def can_show_certificate_message(course, student, course_grade, certificates_ena

def _course_uses_available_date(course):
"""Returns if the course has an certificate_available_date set and that it should be used"""
if settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS"):
display_behavior_is_valid = course.certificates_display_behavior == CertificatesDisplayBehaviors.END_WITH_DATE
else:
display_behavior_is_valid = True
display_behavior_is_valid = course.certificates_display_behavior == CertificatesDisplayBehaviors.END_WITH_DATE

return (
can_show_certificate_available_date_field(course)
Expand Down
26 changes: 1 addition & 25 deletions lms/djangoapps/certificates/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,29 +209,6 @@ def test_with_downloadable_web_cert(self):
"uuid": cert_status["uuid"],
}

@ddt.data(
(False, timedelta(days=2), False, True),
(False, -timedelta(days=2), True, None),
(True, timedelta(days=2), True, None),
)
@ddt.unpack
@patch.dict(settings.FEATURES, {"CERTIFICATES_HTML_VIEW": True})
@patch.dict(settings.FEATURES, {"ENABLE_V2_CERT_DISPLAY_SETTINGS": False})
def test_cert_api_return_v1(self, self_paced, cert_avail_delta, cert_downloadable_status, earned_but_not_available):
"""
Test 'downloadable status'
"""
cert_avail_date = datetime.now(pytz.UTC) + cert_avail_delta
self.course.self_paced = self_paced
self.course.certificate_available_date = cert_avail_date
self.course.save()

self._setup_course_certificate()

downloadable_status = certificate_downloadable_status(self.student, self.course.id)
assert downloadable_status["is_downloadable"] == cert_downloadable_status
assert downloadable_status.get("earned_but_not_available") == earned_but_not_available

@ddt.data(
(True, timedelta(days=2), CertificatesDisplayBehaviors.END_WITH_DATE, True, None),
(False, -timedelta(days=2), CertificatesDisplayBehaviors.EARLY_NO_INFO, True, None),
Expand All @@ -243,8 +220,7 @@ def test_cert_api_return_v1(self, self_paced, cert_avail_delta, cert_downloadabl
)
@ddt.unpack
@patch.dict(settings.FEATURES, {"CERTIFICATES_HTML_VIEW": True})
@patch.dict(settings.FEATURES, {"ENABLE_V2_CERT_DISPLAY_SETTINGS": True})
def test_cert_api_return_v2(
def test_cert_api_return(
self,
self_paced,
cert_avail_delta,
Expand Down
36 changes: 1 addition & 35 deletions lms/djangoapps/certificates/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
from unittest.mock import patch

import ddt
from django.conf import settings
from django.test import TestCase
from pytz import utc

Expand Down Expand Up @@ -80,40 +79,7 @@ def test_has_html_certificates_enabled_from_course_overview_disabled(self):
(CertificatesDisplayBehaviors.END, False, False, _LAST_MONTH, True, True),
)
@ddt.unpack
@patch.dict(settings.FEATURES, ENABLE_V2_CERT_DISPLAY_SETTINGS=True)
def test_should_certificate_be_visible_v2(
self,
certificates_display_behavior,
certificates_show_before_end,
has_ended,
certificate_available_date,
self_paced,
expected_value
):
"""Test whether the certificate should be visible to user given multiple usecases"""
assert should_certificate_be_visible(
certificates_display_behavior,
certificates_show_before_end,
has_ended,
certificate_available_date,
self_paced
) == expected_value

@ddt.data(
('early_with_info', True, True, _LAST_MONTH, False, True),
('early_no_info', False, False, _LAST_MONTH, False, True),
('end', True, False, _LAST_MONTH, False, True),
('end', False, True, _LAST_MONTH, False, True),
('end', False, False, _NEXT_WEEK, False, False),
('end', False, False, _LAST_WEEK, False, True),
('end', False, False, None, False, False),
('early_with_info', False, False, None, False, True),
('end', False, False, _NEXT_WEEK, False, False),
('end', False, False, _NEXT_WEEK, True, True),
)
@ddt.unpack
@patch.dict(settings.FEATURES, ENABLE_V2_CERT_DISPLAY_SETTINGS=False)
def test_should_certificate_be_visible_v1(
def test_should_certificate_be_visible(
self,
certificates_display_behavior,
certificates_show_before_end,
Expand Down
37 changes: 13 additions & 24 deletions lms/djangoapps/certificates/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,30 +153,19 @@ def should_certificate_be_visible(
certificate_available_date (datetime): the date the certificate is available on for the course.
self_paced (bool): Whether the course is self-paced.
"""
if settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS"):
show_early = (
certificates_display_behavior == CertificatesDisplayBehaviors.EARLY_NO_INFO
or certificates_show_before_end
)
past_available_date = (
certificates_display_behavior == CertificatesDisplayBehaviors.END_WITH_DATE
and certificate_available_date
and certificate_available_date < datetime.now(utc)
)
ended_without_available_date = (
certificates_display_behavior == CertificatesDisplayBehaviors.END
and has_ended
)
else:
show_early = (
certificates_display_behavior in ('early_with_info', 'early_no_info')
or certificates_show_before_end
)
past_available_date = (
certificate_available_date
and certificate_available_date < datetime.now(utc)
)
ended_without_available_date = (certificate_available_date is None) and has_ended
show_early = (
certificates_display_behavior == CertificatesDisplayBehaviors.EARLY_NO_INFO
or certificates_show_before_end
)
past_available_date = (
certificates_display_behavior == CertificatesDisplayBehaviors.END_WITH_DATE
and certificate_available_date
and certificate_available_date < datetime.now(utc)
)
ended_without_available_date = (
certificates_display_behavior == CertificatesDisplayBehaviors.END
and has_ended
)

return any((self_paced, show_early, past_available_date, ended_without_available_date))

Expand Down
36 changes: 15 additions & 21 deletions lms/djangoapps/certificates/views/webview.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,28 +353,22 @@ def _get_user_certificate(request, user, course_key, course_overview, preview_mo
if preview_mode:
# certificate is being previewed from studio
if request.user.has_perm(PREVIEW_CERTIFICATES, course_overview):
if not settings.FEATURES.get("ENABLE_V2_CERT_DISPLAY_SETTINGS"):
if course_overview.certificate_available_date and not course_overview.self_paced:
modified_date = course_overview.certificate_available_date
else:
modified_date = datetime.now().date()
if (
course_overview.certificates_display_behavior == CertificatesDisplayBehaviors.END_WITH_DATE
and course_overview.certificate_available_date
and not course_overview.self_paced
):
modified_date = course_overview.certificate_available_date
elif course_overview.certificates_display_behavior == CertificatesDisplayBehaviors.END:
modified_date = course_overview.end
else:
if (
course_overview.certificates_display_behavior == CertificatesDisplayBehaviors.END_WITH_DATE
and course_overview.certificate_available_date
and not course_overview.self_paced
):
modified_date = course_overview.certificate_available_date
elif course_overview.certificates_display_behavior == CertificatesDisplayBehaviors.END:
modified_date = course_overview.end
else:
modified_date = datetime.now().date()
user_certificate = GeneratedCertificate(
mode=preview_mode,
verify_uuid=str(uuid4().hex),
modified_date=modified_date,
created_date=datetime.now().date(),
)
modified_date = datetime.now().date()
user_certificate = GeneratedCertificate(
mode=preview_mode,
verify_uuid=str(uuid4().hex),
modified_date=modified_date,
created_date=datetime.now().date(),
)
elif certificates_viewable_for_course(course_overview):
# certificate is being viewed by learner or public
try:
Expand Down
Loading
Loading