diff --git a/common/lib/xmodule/xmodule/partitions/partitions_service.py b/common/lib/xmodule/xmodule/partitions/partitions_service.py index 8a8ad5c3c8..4db503eaa8 100644 --- a/common/lib/xmodule/xmodule/partitions/partitions_service.py +++ b/common/lib/xmodule/xmodule/partitions/partitions_service.py @@ -89,16 +89,17 @@ class PartitionService(object): with a given course. """ - def __init__(self, course_id, cache=None): + def __init__(self, course_id, cache=None, course=None): self._course_id = course_id self._cache = cache + self.course = course def get_course(self): """ Return the course instance associated with this PartitionService. This default implementation looks up the course from the modulestore. """ - return modulestore().get_course(self._course_id) + return self.course or modulestore().get_course(self._course_id) @property def course_partitions(self): diff --git a/lms/djangoapps/courseware/date_summary.py b/lms/djangoapps/courseware/date_summary.py index 4877e13e74..43c3b0ebf0 100644 --- a/lms/djangoapps/courseware/date_summary.py +++ b/lms/djangoapps/courseware/date_summary.py @@ -20,7 +20,7 @@ from lazy import lazy from pytz import utc from course_modes.models import CourseMode, get_cosmetic_verified_display_price -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, can_show_verified_upgrade from lms.djangoapps.verify_student.models import VerificationDeadline from lms.djangoapps.verify_student.services import IDVerificationService from openedx.core.djangoapps.catalog.utils import get_course_run_details @@ -488,7 +488,7 @@ class VerifiedUpgradeDeadlineDate(DateSummary): if not is_enabled: return False - return verified_upgrade_link_is_valid(self.enrollment) + return can_show_verified_upgrade(self.user, self.enrollment, self.course) @lazy def date(self): diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index ef67dee7af..10101001c2 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -273,7 +273,7 @@ class IndexQueryTestCase(ModuleStoreTestCase): NUM_PROBLEMS = 20 @ddt.data( - (ModuleStoreEnum.Type.mongo, 11, 170), + (ModuleStoreEnum.Type.mongo, 10, 170), (ModuleStoreEnum.Type.split, 4, 168), ) @ddt.unpack diff --git a/lms/djangoapps/courseware/testutils.py b/lms/djangoapps/courseware/testutils.py index df4bab3305..a7613585eb 100644 --- a/lms/djangoapps/courseware/testutils.py +++ b/lms/djangoapps/courseware/testutils.py @@ -155,9 +155,9 @@ class RenderXBlockTestMixin(six.with_metaclass(ABCMeta, object)): return response @ddt.data( - ('vertical_block', ModuleStoreEnum.Type.mongo, 14), + ('vertical_block', ModuleStoreEnum.Type.mongo, 13), ('vertical_block', ModuleStoreEnum.Type.split, 6), - ('html_block', ModuleStoreEnum.Type.mongo, 15), + ('html_block', ModuleStoreEnum.Type.mongo, 14), ('html_block', ModuleStoreEnum.Type.split, 6), ) @ddt.unpack diff --git a/lms/djangoapps/courseware/utils.py b/lms/djangoapps/courseware/utils.py index a378ace954..983b321e4a 100644 --- a/lms/djangoapps/courseware/utils.py +++ b/lms/djangoapps/courseware/utils.py @@ -3,10 +3,13 @@ import datetime +from django.conf import settings from lms.djangoapps.commerce.utils import EcommerceService from pytz import utc from course_modes.models import CourseMode +from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID +from xmodule.partitions.partitions_service import PartitionService def verified_upgrade_deadline_link(user, course=None, course_id=None): @@ -32,17 +35,38 @@ def verified_upgrade_deadline_link(user, course=None, course_id=None): return EcommerceService().upgrade_url(user, course_id) -def verified_upgrade_link_is_valid(enrollment=None): +def can_show_verified_upgrade(user, enrollment, course=None): """ - Return whether this enrollment can be upgraded. + Return whether this user can be shown upgrade message. Arguments: + user (:class:`.AuthUser`): The user from the request.user property enrollment (:class:`.CourseEnrollment`): The enrollment under consideration. If None, then the enrollment is considered to be upgradeable. + course (:class:`.ModulestoreCourse`): Optional passed in modulestore course. + If provided, it is expected to correspond to `enrollment.course.id`. + If not provided, the course will be loaded from the modulestore. + We use the course to retrieve user partitions when calculating whether + the upgrade link will be shown. """ # Return `true` if user is not enrolled in course if enrollment is None: return False + partition_service = PartitionService(enrollment.course.id, course=course) + enrollment_track_partition = partition_service.get_user_partition(ENROLLMENT_TRACK_PARTITION_ID) + group = partition_service.get_group(user, enrollment_track_partition) + current_mode = None + if group: + try: + current_mode = [ + mode.get('slug') for mode in settings.COURSE_ENROLLMENT_MODES.values() if mode['id'] == group.id + ].pop() + except IndexError: + pass + upgradable_mode = not current_mode or current_mode in CourseMode.UPSELL_TO_VERIFIED_MODES + + if not upgradable_mode: + return False upgrade_deadline = enrollment.upgrade_deadline diff --git a/lms/djangoapps/courseware/views/index.py b/lms/djangoapps/courseware/views/index.py index 6b4a6e9473..e8a931ce4e 100644 --- a/lms/djangoapps/courseware/views/index.py +++ b/lms/djangoapps/courseware/views/index.py @@ -520,7 +520,7 @@ class CoursewareIndex(View): ) courseware_context['course_sock_fragment'] = CourseSockFragmentView().render_to_fragment( - request, course=self.course_overview) + request, course=self.course) # entrance exam data self._add_entrance_exam_to_context(courseware_context) diff --git a/lms/djangoapps/experiments/utils.py b/lms/djangoapps/experiments/utils.py index 3e4420e33f..cad02abbd8 100644 --- a/lms/djangoapps/experiments/utils.py +++ b/lms/djangoapps/experiments/utils.py @@ -13,7 +13,7 @@ from opaque_keys.edx.keys import CourseKey from course_modes.models import format_course_price, get_cosmetic_verified_display_price, CourseMode from lms.djangoapps.courseware.access import has_staff_access_to_preview_mode -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, can_show_verified_upgrade from entitlements.models import CourseEntitlement from lms.djangoapps.commerce.utils import EcommerceService from openedx.core.djangoapps.catalog.utils import get_programs @@ -82,9 +82,7 @@ def check_and_get_upgrade_link_and_date(user, enrollment=None, course=None): return (None, None, None) if enrollment: - if course is None: - course = enrollment.course - elif enrollment.course_id != course.id: + if course and enrollment.course_id != course.id: logger.warn(u'{} refers to a different course than {} which was supplied. Enrollment course id={}, ' u'repr={!r}, deprecated={}. Course id={}, repr={!r}, deprecated={}.' .format(enrollment, @@ -116,9 +114,9 @@ def check_and_get_upgrade_link_and_date(user, enrollment=None, course=None): if enrollment is None: return (None, None, None) - if user.is_authenticated and verified_upgrade_link_is_valid(enrollment): + if user.is_authenticated and can_show_verified_upgrade(user, enrollment, course): return ( - verified_upgrade_deadline_link(user, course), + verified_upgrade_deadline_link(user, enrollment.course), enrollment.upgrade_deadline, enrollment.course_upgrade_deadline, ) diff --git a/lms/djangoapps/experiments/views_custom.py b/lms/djangoapps/experiments/views_custom.py index ba3ba252f4..23f4ede863 100644 --- a/lms/djangoapps/experiments/views_custom.py +++ b/lms/djangoapps/experiments/views_custom.py @@ -23,7 +23,7 @@ from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiv from openedx.core.lib.api.permissions import ApiKeyHeaderPermissionIsAuthenticated from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin -from lms.djangoapps.courseware.utils import verified_upgrade_link_is_valid +from lms.djangoapps.courseware.utils import can_show_verified_upgrade from course_modes.models import get_cosmetic_verified_display_price from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.experiments.stable_bucketing import stable_bucketing_hash_group @@ -135,7 +135,7 @@ class Rev934(DeveloperErrorViewMixin, APIView): enrollment = CourseEnrollment.objects.select_related( 'course' ).get(user_id=user.id, course_id=course.id) - user_upsell = verified_upgrade_link_is_valid(enrollment) + user_upsell = can_show_verified_upgrade(user, enrollment) except CourseEnrollment.DoesNotExist: user_upsell = True diff --git a/openedx/core/djangoapps/schedules/resolvers.py b/openedx/core/djangoapps/schedules/resolvers.py index 6437e28238..80c9a325d3 100644 --- a/openedx/core/djangoapps/schedules/resolvers.py +++ b/openedx/core/djangoapps/schedules/resolvers.py @@ -14,7 +14,7 @@ from edx_ace.recipient import Recipient from edx_ace.recipient_resolver import RecipientResolver from edx_django_utils.monitoring import function_trace, set_custom_metric -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, verified_upgrade_link_is_valid +from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link, can_show_verified_upgrade from lms.djangoapps.discussion.notification_prefs.views import UsernameCipher from openedx.core.djangoapps.ace_common.template_context import get_base_template_context from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_SHOW_UNSUBSCRIBE_WAFFLE_SWITCH @@ -343,7 +343,7 @@ def _get_upsell_information_for_schedule(user, schedule): def _get_verified_upgrade_link(user, schedule): enrollment = schedule.enrollment - if enrollment.dynamic_upgrade_deadline is not None and verified_upgrade_link_is_valid(enrollment): + if enrollment.dynamic_upgrade_deadline is not None and can_show_verified_upgrade(user, enrollment): return verified_upgrade_deadline_link(user, enrollment.course) diff --git a/openedx/features/course_experience/utils.py b/openedx/features/course_experience/utils.py index d6b90880e4..d8c0364f12 100644 --- a/openedx/features/course_experience/utils.py +++ b/openedx/features/course_experience/utils.py @@ -7,7 +7,6 @@ import logging from datetime import timedelta from completion.models import BlockCompletion -from django.conf import settings from django.utils import timezone from opaque_keys.edx.keys import CourseKey from six.moves import range @@ -16,13 +15,10 @@ from course_modes.models import CourseMode from lms.djangoapps.course_api.blocks.api import get_blocks from lms.djangoapps.course_blocks.utils import get_student_module_as_dict from lms.djangoapps.courseware.access import has_access -from lms.djangoapps.courseware.utils import verified_upgrade_link_is_valid from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.lib.cache_utils import request_cached from student.models import CourseEnrollment from xmodule.modulestore.django import modulestore -from xmodule.partitions.partitions import ENROLLMENT_TRACK_PARTITION_ID -from xmodule.partitions.partitions_service import PartitionService log = logging.getLogger(__name__) @@ -295,25 +291,3 @@ def reset_deadlines_banner_should_display(course_key, request): display_reset_dates_banner = True break return display_reset_dates_banner - - -def can_show_verified_upgrade(user, course_id, enrollment): - """ - Check if we are able to show verified upgrade message based - on the enrollment and current user partition - """ - if not enrollment: - return False - partition_service = PartitionService(course_id) - enrollment_track_partition = partition_service.get_user_partition(ENROLLMENT_TRACK_PARTITION_ID) - group = partition_service.get_group(user, enrollment_track_partition) - current_mode = None - if group: - try: - current_mode = [ - mode.get('slug') for mode in settings.COURSE_ENROLLMENT_MODES.values() if mode['id'] == group.id - ].pop() - except IndexError: - pass - upgradable_mode = not current_mode or current_mode in CourseMode.UPSELL_TO_VERIFIED_MODES - return upgradable_mode and verified_upgrade_link_is_valid(enrollment) diff --git a/openedx/features/course_experience/views/course_home.py b/openedx/features/course_experience/views/course_home.py index 31c7f3c54c..7c390e5d55 100644 --- a/openedx/features/course_experience/views/course_home.py +++ b/openedx/features/course_experience/views/course_home.py @@ -24,6 +24,7 @@ from lms.djangoapps.course_goals.api import ( has_course_goal_permission ) from lms.djangoapps.courseware.exceptions import CourseAccessRedirect +from lms.djangoapps.courseware.utils import can_show_verified_upgrade, verified_upgrade_deadline_link from lms.djangoapps.courseware.views.views import CourseTabView from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.plugin_api.views import EdxFragmentView @@ -42,7 +43,7 @@ from .. import ( SHOW_UPGRADE_MSG_ON_COURSE_HOME, USE_BOOTSTRAP_FLAG ) -from ..utils import can_show_verified_upgrade, get_course_outline_block_tree, get_resume_block +from ..utils import get_course_outline_block_tree, get_resume_block from .course_dates import CourseDatesFragmentView from .course_home_messages import CourseHomeMessageFragmentView from .course_outline import CourseOutlineFragmentView @@ -165,7 +166,7 @@ class CourseHomeFragmentView(EdxFragmentView): request, course_id=course_id, **kwargs ) course_sock_fragment = CourseSockFragmentView().render_to_fragment( - request, course=course_overview, **kwargs + request, course=course, **kwargs ) has_visited_course, resume_course_url, resume_course_title = self._get_resume_course_info( request, course_id @@ -224,10 +225,10 @@ class CourseHomeFragmentView(EdxFragmentView): # TODO Add switch to control deployment if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled(course_key) and can_show_verified_upgrade( request.user, - course.id, - enrollment + enrollment, + course ): - upgrade_url = EcommerceService().upgrade_url(request.user, course_key) + upgrade_url = verified_upgrade_deadline_link(request.user, course_id=course_key) upgrade_price, has_discount = format_strikeout_price(request.user, course_overview) show_search = ( diff --git a/openedx/features/course_experience/views/course_sock.py b/openedx/features/course_experience/views/course_sock.py index 98646d9e3a..ae06fd2995 100644 --- a/openedx/features/course_experience/views/course_sock.py +++ b/openedx/features/course_experience/views/course_sock.py @@ -5,13 +5,14 @@ Fragment for rendering the course's sock and associated toggle button. from django.template.loader import render_to_string from web_fragments.fragment import Fragment -from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link +from lms.djangoapps.courseware.utils import ( + can_show_verified_upgrade, + verified_upgrade_deadline_link +) from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.features.discounts.utils import format_strikeout_price from student.models import CourseEnrollment -from ..utils import can_show_verified_upgrade - class CourseSockFragmentView(EdxFragmentView): """ @@ -28,7 +29,7 @@ class CourseSockFragmentView(EdxFragmentView): @staticmethod def get_verification_context(request, course): enrollment = CourseEnrollment.get_enrollment(request.user, course.id) - show_course_sock = can_show_verified_upgrade(request.user, course.id, enrollment) + show_course_sock = can_show_verified_upgrade(request.user, enrollment, course) if show_course_sock: upgrade_url = verified_upgrade_deadline_link(request.user, course=course) course_price, _ = format_strikeout_price(request.user, course)