Skip to content

Commit

Permalink
feat: [AXM-53] add assertions for primary course
Browse files Browse the repository at this point in the history
  • Loading branch information
NiedielnitsevIvan committed Mar 28, 2024
1 parent ad358c7 commit 89acefe
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
46 changes: 40 additions & 6 deletions lms/djangoapps/mobile_api/users/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Serializer for user API
"""

from datetime import datetime
from typing import Dict, List, Optional, Tuple

from django.core.cache import cache
Expand All @@ -16,8 +17,10 @@
from lms.djangoapps.certificates.api import certificate_downloadable_status
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.courseware.block_render import get_block_for_descriptor
from lms.djangoapps.courseware.courses import get_current_child
from lms.djangoapps.courseware.context_processor import get_user_timezone_or_last_seen_timezone_or_utc
from lms.djangoapps.courseware.courses import get_course_assignment_date_blocks, get_current_child
from lms.djangoapps.courseware.model_data import FieldDataCache
from lms.djangoapps.course_home_api.dates.serializers import DateSummarySerializer
from lms.djangoapps.grades.api import CourseGradeFactory
from openedx.core.djangoapps.content.block_structure.api import get_block_structure_manager
from openedx.features.course_duration_limits.access import get_user_course_expiration_date
Expand Down Expand Up @@ -160,9 +163,15 @@ class CourseEnrollmentSerializerModifiedForPrimary(CourseEnrollmentSerializer):

course_status = serializers.SerializerMethodField()
progress = serializers.SerializerMethodField()
course_assignments = serializers.SerializerMethodField()

BLOCK_STRUCTURE_CACHE_TIMEOUT = 60 * 60 # 1 hour

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# import pdb; pdb.set_trace()
self.course = modulestore().get_course(self.instance.course.id)

def get_course_status(self, model: CourseEnrollment) -> Optional[Dict[str, List[str]]]:
"""
Gets course status for the given user's enrollments.
Expand All @@ -186,8 +195,8 @@ def get_course_status(self, model: CourseEnrollment) -> Optional[Dict[str, List[
'last_visited_unit_display_name': unit_name,
}

@staticmethod
def _get_last_visited_block_path_and_unit_name(
self,
request: 'Request', # noqa: F821
model: CourseEnrollment,
) -> Tuple[List[Optional['XBlock']], Optional[str]]: # noqa: F821
Expand All @@ -197,12 +206,10 @@ def _get_last_visited_block_path_and_unit_name(
If there is no such visit, the first item deep enough down the course
tree is used.
"""
course = modulestore().get_course(model.course.id)
field_data_cache = FieldDataCache.cache_for_block_descendents(
course.id, model.user, course, depth=3)
field_data_cache = FieldDataCache.cache_for_block_descendents(self.course.id, model.user, self.course, depth=3)

course_block = get_block_for_descriptor(
model.user, request, course, field_data_cache, course.id, course=course
model.user, request, self.course, field_data_cache, self.course.id, course=self.course
)

unit_name = ''
Expand Down Expand Up @@ -243,6 +250,32 @@ def get_progress(self, model: CourseEnrollment) -> Dict[str, int]:
'num_points_possible': sum(map(lambda x: x.graded_total.possible if x.graded else 0, subsection_grades)),
}

def get_course_assignments(self, model: CourseEnrollment) -> Optional[Dict[str, List[Dict[str, str]]]]:
"""
Returns the future assignment data and past assignments data for the user in the course.
"""
assignments = get_course_assignment_date_blocks(
self.course,
model.user,
self.context.get('request'),
include_past_dates=True
)
next_assignment = {}
past_assignment = []

timezone = get_user_timezone_or_last_seen_timezone_or_utc(model.user)
for assignment in sorted(assignments, key=lambda x: x.date):
if assignment.date < datetime.now(timezone):
past_assignment.append(assignment)
else:
if not next_assignment:
next_assignment = DateSummarySerializer(assignment).data

return {
'future_assignment': next_assignment,
'past_assignments': DateSummarySerializer(past_assignment, many=True).data,
}

class Meta:
model = CourseEnrollment
fields = (
Expand All @@ -255,6 +288,7 @@ class Meta:
'course_modes',
'course_status',
'progress',
'course_assignments',
)
lookup_field = 'username'

Expand Down
12 changes: 10 additions & 2 deletions lms/djangoapps/mobile_api/users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.contrib.auth.signals import user_logged_in
from django.db import transaction
from django.shortcuts import redirect
from django.shortcuts import get_object_or_404, redirect
from django.utils import dateparse
from django.utils.decorators import method_decorator
from opaque_keys import InvalidKeyError
Expand All @@ -28,6 +28,7 @@
from common.djangoapps.student.models import CourseEnrollment, User # lint-amnesty, pylint: disable=reimported
from lms.djangoapps.courseware.access import is_mobile_available_for_user
from lms.djangoapps.courseware.access_utils import ACCESS_GRANTED
from lms.djangoapps.courseware.context_processor import get_user_timezone_or_last_seen_timezone_or_utc
from lms.djangoapps.courseware.courses import get_current_child
from lms.djangoapps.courseware.model_data import FieldDataCache
from lms.djangoapps.courseware.block_render import get_block_for_descriptor
Expand Down Expand Up @@ -358,7 +359,7 @@ def queryset(self):
return CourseEnrollment.objects.all().select_related('course', 'user').filter(
user__username=self.kwargs['username'],
is_active=True
).order_by('created').reverse()
).order_by('-created')

def get_queryset(self):
api_version = self.kwargs.get('api_version')
Expand Down Expand Up @@ -404,6 +405,7 @@ def list(self, request, *args, **kwargs):
if api_version in (API_V2, API_V3, API_V4):
enrollment_data = {
'configs': MobileConfig.get_structured_configs(),
'user_timezone': str(get_user_timezone_or_last_seen_timezone_or_utc(self.get_user())),
'enrollments': response.data
}
if api_version == API_V4:
Expand All @@ -419,6 +421,12 @@ def list(self, request, *args, **kwargs):

return response

def get_user(self) -> User:
"""
Get user object by username.
"""
return get_object_or_404(User, username=self.kwargs['username'])

def get_primary_enrollment_by_latest_enrollment_or_progress(self) -> Optional[CourseEnrollment]:
"""
Gets primary enrollment obj by latest enrollment or latest progress on the course.
Expand Down

0 comments on commit 89acefe

Please sign in to comment.