From 12a6866eb57f148ca0ce259f2efb719a77b4b978 Mon Sep 17 00:00:00 2001 From: KyryloKireiev Date: Wed, 3 Jul 2024 17:29:19 +0300 Subject: [PATCH] refactor: [AXM-506] Refactor user's enrolments API --- .../student/models/course_enrollment.py | 38 ++++++++++--------- lms/djangoapps/courseware/courses.py | 3 +- lms/djangoapps/mobile_api/users/views.py | 14 +++---- 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/common/djangoapps/student/models/course_enrollment.py b/common/djangoapps/student/models/course_enrollment.py index 9fd53c1cd796..09862916e321 100644 --- a/common/djangoapps/student/models/course_enrollment.py +++ b/common/djangoapps/student/models/course_enrollment.py @@ -140,50 +140,52 @@ def active(self): """ return self.filter(is_active=True) - def without_certificates(self, user_username): + def without_certificates(self, username): """ Returns a queryset of CourseEnrollment objects for courses that do not have a certificate. """ - from lms.djangoapps.certificates.models import GeneratedCertificate # pylint: disable=import-outside-toplevel - course_ids_with_certificates = GeneratedCertificate.objects.filter( - user__username=user_username - ).values_list('course_id', flat=True) - return self.exclude(course_id__in=course_ids_with_certificates) + return self.exclude(course_id__in=self.get_user_course_ids_with_certificates(username)) - def with_certificates(self, user_username): + def with_certificates(self, username): """ Returns a queryset of CourseEnrollment objects for courses that have a certificate. """ - from lms.djangoapps.certificates.models import GeneratedCertificate # pylint: disable=import-outside-toplevel - course_ids_with_certificates = GeneratedCertificate.objects.filter( - user__username=user_username - ).values_list('course_id', flat=True) - return self.filter(course_id__in=course_ids_with_certificates) + return self.filter(course_id__in=self.get_user_course_ids_with_certificates(username)) - def in_progress(self, user_username, time_zone=UTC): + def in_progress(self, username, time_zone=UTC): """ Returns a queryset of CourseEnrollment objects for courses that are currently in progress. """ now = datetime.now(time_zone) - return self.active().without_certificates(user_username).filter( + return self.active().without_certificates(username).filter( Q(course__start__lte=now, course__end__gte=now) | Q(course__start__isnull=True, course__end__isnull=True) | Q(course__start__isnull=True, course__end__gte=now) | Q(course__start__lte=now, course__end__isnull=True), ) - def completed(self, user_username): + def completed(self, username): """ Returns a queryset of CourseEnrollment objects for courses that have been completed. """ - return self.active().with_certificates(user_username) + return self.active().with_certificates(username) - def expired(self, user_username, time_zone=UTC): + def expired(self, username, time_zone=UTC): """ Returns a queryset of CourseEnrollment objects for courses that have expired. """ now = datetime.now(time_zone) - return self.active().without_certificates(user_username).filter(course__end__lt=now) + return self.active().without_certificates(username).filter(course__end__lt=now) + + def get_user_course_ids_with_certificates(self, username): + """ + Gets user's course ids with certificates. + """ + from lms.djangoapps.certificates.models import GeneratedCertificate # pylint: disable=import-outside-toplevel + course_ids_with_certificates = GeneratedCertificate.objects.filter( + user__username=username + ).values_list('course_id', flat=True) + return course_ids_with_certificates class CourseEnrollmentManager(models.Manager): diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index 948f3bd5db44..0ff6a11a627b 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -787,7 +787,8 @@ def get_assignments_grades(user, course_id, cache_timeout): is_staff = bool(has_access(user, 'staff', course_id)) try: - cache_key = f'course_block_structure_{str(course_id)}_{user.id}' + course = get_course_with_access(user, 'load', course_id) + cache_key = f'course_block_structure_{str(course_id)}_{str(course.course_version)}_{user.id}' collected_block_structure = cache.get(cache_key) if not collected_block_structure: collected_block_structure = get_block_structure_manager(course_id).get_collected() diff --git a/lms/djangoapps/mobile_api/users/views.py b/lms/djangoapps/mobile_api/users/views.py index 44900b53b03f..d959e188b4ee 100644 --- a/lms/djangoapps/mobile_api/users/views.py +++ b/lms/djangoapps/mobile_api/users/views.py @@ -363,7 +363,7 @@ def get_serializer_class(self): return CourseEnrollmentSerializer @cached_property - def queryset(self): + def queryset_for_user(self): """ Find and return the list of course enrollments for the user. @@ -380,11 +380,11 @@ def queryset(self): if api_version == API_V4 and status in EnrollmentStatuses.values(): if status == EnrollmentStatuses.IN_PROGRESS.value: - queryset = queryset.in_progress(user_username=username, time_zone=self.user_timezone) + queryset = queryset.in_progress(username=username, time_zone=self.user_timezone) elif status == EnrollmentStatuses.COMPLETED.value: - queryset = queryset.completed(user_username=username) + queryset = queryset.completed(username=username) elif status == EnrollmentStatuses.EXPIRED.value: - queryset = queryset.expired(user_username=username, time_zone=self.user_timezone) + queryset = queryset.expired(username=username, time_zone=self.user_timezone) return queryset @@ -417,7 +417,7 @@ def get_same_org_mobile_available_enrollments(self) -> list[CourseEnrollment]: org = self.request.query_params.get('org', None) same_org = ( - enrollment for enrollment in self.queryset + enrollment for enrollment in self.queryset_for_user if enrollment.course_overview and self.is_org(org, enrollment.course_overview.org) ) mobile_available = ( @@ -473,7 +473,7 @@ def get_primary_enrollment_by_latest_enrollment_or_progress(self) -> Optional[Co mobile_available_course_ids = [enrollment.course_id for enrollment in mobile_available] - latest_enrollment = self.queryset.filter( + latest_enrollment = self.queryset_for_user.filter( course__id__in=mobile_available_course_ids ).order_by('-created').first() @@ -488,7 +488,7 @@ def get_primary_enrollment_by_latest_enrollment_or_progress(self) -> Optional[Co if not latest_progress: return latest_enrollment - enrollment_with_latest_progress = self.queryset.filter( + enrollment_with_latest_progress = self.queryset_for_user.filter( course_id=latest_progress.course_id, user__username=self.kwargs['username'], ).first()