diff --git a/openedx/core/djangoapps/courseware_api/serializers.py b/openedx/core/djangoapps/courseware_api/serializers.py index be2164e5d1..712cb71b85 100644 --- a/openedx/core/djangoapps/courseware_api/serializers.py +++ b/openedx/core/djangoapps/courseware_api/serializers.py @@ -56,6 +56,22 @@ class _CourseApiMediaCollectionSerializer(serializers.Serializer): # pylint: di ref_name = 'courseware_api' +class CourseProgramSerializer(serializers.Serializer): + progress = serializers.SerializerMethodField() + slug = serializers.CharField() + title = serializers.CharField() + url = AbsoluteURLField() + uuid = serializers.UUIDField() + + def get_progress(self, program): + progress = program['progress'] + return { + 'completed': progress['completed'], + 'in_progress': progress['in_progress'], + 'not_started': progress['not_started'] + } + + class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract-method """ Serializer for Course objects providing minimal data about the course. @@ -76,6 +92,7 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract- number = serializers.CharField(source='display_number_with_default') offer_html = serializers.CharField() org = serializers.CharField(source='display_org_with_default') + related_programs = CourseProgramSerializer(many=True) short_description = serializers.CharField() start = serializers.DateTimeField() start_display = serializers.CharField() diff --git a/openedx/core/djangoapps/courseware_api/views.py b/openedx/core/djangoapps/courseware_api/views.py index a6c3e4e3f7..9c57c1fb34 100644 --- a/openedx/core/djangoapps/courseware_api/views.py +++ b/openedx/core/djangoapps/courseware_api/views.py @@ -39,6 +39,7 @@ from lms.djangoapps.courseware.views.views import get_cert_data from lms.djangoapps.grades.api import CourseGradeFactory from lms.djangoapps.verify_student.services import IDVerificationService from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin +from openedx.core.djangoapps.programs.utils import ProgramProgressMeter from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG from openedx.features.content_type_gating.models import ContentTypeGatingConfig from openedx.features.course_duration_limits.access import ( @@ -281,6 +282,37 @@ class CoursewareMeta: self.overview.display_name, user_certificate.mode, cert_url, certificate=user_certificate, ) + @property + def related_programs(self): + """ + Returns related program data if the effective_user is enrolled. + Note: related programs can be None depending on the course. + """ + if self.effective_user.is_anonymous: + return + + meter = ProgramProgressMeter(self.request.site, self.effective_user) + inverted_programs = meter.invert_programs() + related_programs = inverted_programs.get(str(self.course_key)) + + if related_programs is None: + return + + related_progress = meter.progress(programs=related_programs) + progress_by_program = { + progress['uuid']: progress for progress in related_progress + } + + programs = [{ + 'progress': progress_by_program[program['uuid']], + 'title': program['title'], + 'slug': program['type_attrs']['slug'], + 'url': program['detail_url'], + 'uuid': program['uuid'] + } for program in related_programs] + + return programs + class CoursewareInformation(RetrieveAPIView): """ @@ -310,6 +342,17 @@ class CoursewareInformation(RetrieveAPIView): * name: Name of the course * number: Catalog number of the course * org: Name of the organization that owns the course + * related_programs: A list of objects that contains program data related to the given course including: + * progress: An object containing program progress: + * complete: (int) Number of complete courses in the program (a course is completed if the user has + earned a certificate for any of the nested course runs) + * in_progress: (int) Number of courses in the program that are in progress (a course is in progress if + the user has enrolled in any of the nested course runs) + * not_started: (int) Number of courses in the program that have not been started + * slug: (str) The program type + * title: (str) The title of the program + * url: (str) The link to the program's landing page + * uuid: (str) A unique identifier of the program * short_description: A textual description of the course * start: Date the course begins, in ISO 8601 notation * start_display: Readably formatted start of the course