diff --git a/docs/swagger.yaml b/docs/swagger.yaml index b697b8bb1a..e5e2246288 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -2196,6 +2196,9 @@ paths: * `"timestamp"`: generated from the `start` timestamp * `"empty"`: no start date is specified * pacing: Course pacing. Possible values: instructor, self + * certificate_available_date (optional): Date the certificate will be available, + in ISO 8601 notation if the `certificates.auto_certificate_generation` + waffle switch is enabled Deprecated fields: @@ -2240,7 +2243,8 @@ paths: "start": "2015-07-17T12:00:00Z", "start_display": "July 17, 2015", "start_type": "timestamp", - "pacing": "instructor" + "pacing": "instructor", + "certificate_available_date": "2015-08-14T00:00:00Z" } parameters: [] responses: diff --git a/lms/djangoapps/course_api/serializers.py b/lms/djangoapps/course_api/serializers.py index d9188a51c4..dbf4736d4e 100644 --- a/lms/djangoapps/course_api/serializers.py +++ b/lms/djangoapps/course_api/serializers.py @@ -9,6 +9,7 @@ from django.urls import reverse from edx_django_utils import monitoring as monitoring_utils from rest_framework import serializers +from lms.djangoapps.certificates.api import can_show_certificate_available_date_field from openedx.core.djangoapps.content.course_overviews.models import \ CourseOverview # lint-amnesty, pylint: disable=unused-import from openedx.core.djangoapps.models.course_details import CourseDetails @@ -159,6 +160,16 @@ class CourseDetailSerializer(CourseSerializer): # pylint: disable=abstract-meth # from the CourseOverview object in SQL. return CourseDetails.fetch_about_attribute(course_overview.id, 'overview') + def to_representation(self, instance): + """ + Get the `certificate_available_date` in response + if the `certificates.auto_certificate_generation` waffle switch is enabled + """ + response = super().to_representation(instance) + if can_show_certificate_available_date_field(instance): + response['certificate_available_date'] = instance.certificate_available_date + return response + class CourseKeySerializer(serializers.BaseSerializer): # pylint:disable=abstract-method """ diff --git a/lms/djangoapps/course_api/tests/mixins.py b/lms/djangoapps/course_api/tests/mixins.py index 2434443e87..2940826c68 100644 --- a/lms/djangoapps/course_api/tests/mixins.py +++ b/lms/djangoapps/course_api/tests/mixins.py @@ -25,6 +25,7 @@ class CourseApiFactoryMixin: end=end, enrollment_start=datetime(2015, 6, 15, 0, 0, 0), enrollment_end=datetime(2015, 7, 15, 0, 0, 0), + certificate_available_date=datetime(2015, 8, 14, 0, 0, 0), emit_signals=True, **kwargs ) diff --git a/lms/djangoapps/course_api/tests/test_serializers.py b/lms/djangoapps/course_api/tests/test_serializers.py index 045f399f4e..4ee5e10265 100644 --- a/lms/djangoapps/course_api/tests/test_serializers.py +++ b/lms/djangoapps/course_api/tests/test_serializers.py @@ -4,7 +4,7 @@ Test data created by CourseSerializer and CourseDetailSerializer from datetime import datetime -from unittest import TestCase +from unittest import TestCase, mock import ddt from opaque_keys.edx.locator import CourseLocator @@ -15,6 +15,7 @@ from xmodule.course_block import DEFAULT_START_DATE from xmodule.modulestore.tests.django_utils import TEST_DATA_MONGO_AMNESTY_MODULESTORE, ModuleStoreTestCase from xmodule.modulestore.tests.factories import check_mongo_calls +from lms.djangoapps.certificates.api import can_show_certificate_available_date_field from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.models.course_details import CourseDetails @@ -166,6 +167,32 @@ class TestCourseDetailSerializer(TestCourseSerializer): # lint-amnesty, pylint: overview_template = about_descriptor.get_template('overview.yaml') self.expected_data['overview'] = overview_template.get('data') + # override test case + @mock.patch( + "lms.djangoapps.certificates.api.can_show_certificate_available_date_field", + mock.Mock(return_value=[True, False]) + ) + def test_basic(self): + """ + Overridden from Test CourseDetailSerializer to + test certificate_available_date according to waffle + switch `certificates.auto_certificate_generation` + from CourseDetailSerializer serializer class. + """ + course = self.create_course() + CourseDetails.update_about_video(course, 'test_youtube_id', self.staff_user.id) + course_overview = CourseOverview.get_from_id(course.id) + with check_mongo_calls(self.expected_mongo_calls): + result = self._get_result(course) + if can_show_certificate_available_date_field(course_overview): + self.expected_data['certificate_available_date'] = '2015-08-14T00:00:00Z' + result['certificate_available_date'] = ( + result['certificate_available_date'].strftime('%Y-%m-%dT%H:%M:%SZ') + if isinstance(result['certificate_available_date'], datetime) + else None + ) + self.assertDictEqual(result, self.expected_data) + class TestCourseKeySerializer(TestCase): # lint-amnesty, pylint: disable=missing-class-docstring diff --git a/lms/djangoapps/course_api/views.py b/lms/djangoapps/course_api/views.py index cee7d7cbb9..fbb8517cf0 100644 --- a/lms/djangoapps/course_api/views.py +++ b/lms/djangoapps/course_api/views.py @@ -59,6 +59,9 @@ class CourseDetailView(DeveloperErrorViewMixin, RetrieveAPIView): * `"timestamp"`: generated from the `start` timestamp * `"empty"`: no start date is specified * pacing: Course pacing. Possible values: instructor, self + * certificate_available_date (optional): Date the certificate will be available, + in ISO 8601 notation if the `certificates.auto_certificate_generation` + waffle switch is enabled Deprecated fields: @@ -103,7 +106,8 @@ class CourseDetailView(DeveloperErrorViewMixin, RetrieveAPIView): "start": "2015-07-17T12:00:00Z", "start_display": "July 17, 2015", "start_type": "timestamp", - "pacing": "instructor" + "pacing": "instructor", + "certificate_available_date": "2015-08-14T00:00:00Z" } """