Skip to content
Snippets Groups Projects
Commit 8ff937c3 authored by Matthew Piatetsky's avatar Matthew Piatetsky
Browse files

feat: Add new data to course home and progress endpoints to support the...

feat: Add new data to course home and progress endpoints to support the progress page certificate status component
AA-719
parent a21d0ff2
No related branches found
No related tags found
No related merge requests found
......@@ -86,6 +86,9 @@ class ProgressTabSerializer(serializers.Serializer):
certificate_data = CertificateDataSerializer()
completion_summary = serializers.DictField()
course_grade = CourseGradeSerializer()
end = serializers.DateTimeField()
user_has_passing_grade = serializers.BooleanField()
has_scheduled_content = serializers.BooleanField()
section_scores = SectionScoresSerializer(many=True)
enrollment_mode = serializers.CharField()
grading_policy = GradingPolicySerializer()
......
......@@ -2,8 +2,14 @@
Tests for Progress Tab API in the Course Home API
"""
import dateutil
import ddt
import mock
from datetime import timedelta
from pytz import UTC
from unittest.mock import patch
from django.urls import reverse
from django.utils.timezone import now
from edx_toggles.toggles.testutils import override_waffle_flag
from common.djangoapps.course_modes.models import CourseMode
......@@ -14,6 +20,7 @@ from lms.djangoapps.course_home_api.toggles import COURSE_HOME_MICROFRONTEND, CO
from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag
from lms.djangoapps.verify_student.models import ManualVerification
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
from xmodule.modulestore.tests.factories import ItemFactory
CREDIT_SUPPORT_URL = 'https://support.edx.org/hc/en-us/sections/115004154688-Purchasing-Academic-Credit'
......@@ -97,3 +104,36 @@ class ProgressTabTestViews(BaseCourseHomeTests):
# Masquerade as verified user
self.update_masquerade(username=verified_user.username)
assert self.client.get(self.url).data.get('enrollment_mode') == 'verified'
@patch.dict('django.conf.settings.FEATURES', {'DISABLE_START_DATES': False})
@override_experiment_waffle_flag(COURSE_HOME_MICROFRONTEND, active=True)
@override_waffle_flag(COURSE_HOME_MICROFRONTEND_PROGRESS_TAB, active=True)
def test_has_scheduled_content_data(self):
CourseEnrollment.enroll(self.user, self.course.id)
future = now() + timedelta(days=30)
chapter = ItemFactory(parent=self.course, category='chapter', start=future)
response = self.client.get(self.url)
assert response.status_code == 200
assert response.json()['has_scheduled_content']
@override_experiment_waffle_flag(COURSE_HOME_MICROFRONTEND, active=True)
@override_waffle_flag(COURSE_HOME_MICROFRONTEND_PROGRESS_TAB, active=True)
def test_end(self):
CourseEnrollment.enroll(self.user, self.course.id)
future = now() + timedelta(days=30)
self.course.end = future
self.update_course(self.course, self.user.id)
response = self.client.get(self.url)
assert response.status_code == 200
end = dateutil.parser.parse(response.json()['end']).replace(tzinfo=UTC)
assert end.date() == future.date()
@override_experiment_waffle_flag(COURSE_HOME_MICROFRONTEND, active=True)
@override_waffle_flag(COURSE_HOME_MICROFRONTEND_PROGRESS_TAB, active=True)
def test_user_has_passing_grade(self):
CourseEnrollment.enroll(self.user, self.course.id)
self.course._grading_policy['GRADE_CUTOFFS']['Pass'] = 0
self.update_course(self.course, self.user.id)
response = self.client.get(self.url)
assert response.status_code == 200
assert response.json()['user_has_passing_grade']
......@@ -16,12 +16,17 @@ from common.djangoapps.student.models import CourseEnrollment
from lms.djangoapps.course_home_api.progress.v1.serializers import ProgressTabSerializer
from lms.djangoapps.course_home_api.toggles import course_home_mfe_progress_tab_is_active
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.course_blocks.api import get_course_blocks
from lms.djangoapps.course_blocks.transformers import start_date
from lms.djangoapps.courseware.courses import get_course_blocks_completion_summary, get_course_with_access, get_studio_url
from lms.djangoapps.courseware.masquerade import setup_masquerade
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.djangoapps.content.block_structure.transformers import BlockStructureTransformers
from openedx.core.djangoapps.content.block_structure.api import get_block_structure_manager
from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
......@@ -39,6 +44,9 @@ class ProgressTabView(RetrieveAPIView):
Body consists of the following fields:
end: (date) end date of the course
user_has_passing_grade: (bool) boolean on if the user has a passing grade in the course
has_scheduled_content: (bool) boolean on if the course has content scheduled with a release date in the future
certificate_data: Object containing information about the user's certificate status
cert_status: (str) the status of a user's certificate (full list of statuses are defined in
lms/djangoapps/certificates/models.py)
......@@ -122,11 +130,32 @@ class ProgressTabView(RetrieveAPIView):
enrollment_mode, _ = CourseEnrollment.enrollment_mode_for_user(request.user, course_key)
course_grade = CourseGradeFactory().read(request.user, course)\
# The block structure is used for both the course_grade and has_scheduled content fields
# So it is called upfront and reused for optimization purposes
collected_block_structure = get_block_structure_manager(course_key).get_collected()
course_grade = CourseGradeFactory().read(request.user, collected_block_structure=collected_block_structure)
# Get has_scheduled_content data
transformers = BlockStructureTransformers()
transformers += [start_date.StartDateTransformer()]
usage_key = collected_block_structure.root_block_usage_key
course_blocks = get_course_blocks(
request.user,
usage_key,
transformers=transformers,
collected_block_structure=collected_block_structure,
include_has_scheduled_content=True
)
has_scheduled_content = course_blocks.get_xblock_field(usage_key, 'has_scheduled_content')
# Get user_has_passing_grade data
user_has_passing_grade = False
if not request.user.is_anonymous:
user_grade = course_grade.percent
user_has_passing_grade = user_grade >= course.lowest_passing_grade
descriptor = modulestore().get_course(course_key)
grading_policy = descriptor.grading_policy
verification_status = IDVerificationService.user_status(request.user)
verification_link = None
if verification_status['status'] is None or verification_status['status'] == 'expired':
......@@ -140,9 +169,12 @@ class ProgressTabView(RetrieveAPIView):
}
data = {
'end': course.end,
'user_has_passing_grade': user_has_passing_grade,
'certificate_data': get_cert_data(request.user, course, enrollment_mode, course_grade),
'completion_summary': get_course_blocks_completion_summary(course_key, request.user),
'course_grade': course_grade,
'has_scheduled_content': has_scheduled_content,
'section_scores': course_grade.chapter_grades.values(),
'enrollment_mode': enrollment_mode,
'grading_policy': grading_policy,
......
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