diff --git a/common/djangoapps/entitlements/rest_api/v1/permissions.py b/common/djangoapps/entitlements/rest_api/v1/permissions.py index 6a705d9fee..db14f05049 100644 --- a/common/djangoapps/entitlements/rest_api/v1/permissions.py +++ b/common/djangoapps/entitlements/rest_api/v1/permissions.py @@ -4,7 +4,6 @@ requiring Superuser access for all other Request types on an API endpoint. """ -from django.conf import settings from rest_framework.permissions import SAFE_METHODS, BasePermission from lms.djangoapps.courseware.access import has_access @@ -22,12 +21,3 @@ class IsAdminOrSupportOrAuthenticatedReadOnly(BasePermission): return request.user.is_authenticated else: return request.user.is_staff or has_access(request.user, "support", "global") - - -class IsSubscriptionWorkerUser(BasePermission): - """ - Method that will require the request to be coming from the subscriptions service worker user. - """ - - def has_permission(self, request, view): - return request.user.username == settings.SUBSCRIPTIONS_SERVICE_WORKER_USERNAME diff --git a/common/djangoapps/entitlements/rest_api/v1/tests/test_views.py b/common/djangoapps/entitlements/rest_api/v1/tests/test_views.py index 34abc39c00..86d4ae6a87 100644 --- a/common/djangoapps/entitlements/rest_api/v1/tests/test_views.py +++ b/common/djangoapps/entitlements/rest_api/v1/tests/test_views.py @@ -6,7 +6,6 @@ import logging import uuid from datetime import datetime, timedelta from unittest.mock import patch -from uuid import uuid4 from django.conf import settings from django.urls import reverse @@ -1236,160 +1235,3 @@ class EntitlementEnrollmentViewSetTest(ModuleStoreTestCase): assert CourseEnrollment.is_enrolled(self.user, self.course.id) assert course_entitlement.enrollment_course_run is not None assert course_entitlement.expired_at is None - - -@skip_unless_lms -class RevokeSubscriptionsVerifiedAccessViewTest(ModuleStoreTestCase): - """ - Tests for the RevokeVerifiedAccessView - """ - REVOKE_VERIFIED_ACCESS_PATH = 'entitlements_api:v1:revoke_subscriptions_verified_access' - - def setUp(self): - super().setUp() - self.user = UserFactory(username="subscriptions_worker", is_staff=True) - self.client.login(username=self.user.username, password=TEST_PASSWORD) - self.course = CourseFactory() - self.course_mode1 = CourseModeFactory( - course_id=self.course.id, # pylint: disable=no-member - mode_slug=CourseMode.VERIFIED, - expiration_datetime=now() + timedelta(days=1) - ) - self.course_mode2 = CourseModeFactory( - course_id=self.course.id, # pylint: disable=no-member - mode_slug=CourseMode.AUDIT, - expiration_datetime=now() + timedelta(days=1) - ) - - @patch('common.djangoapps.entitlements.rest_api.v1.views.get_courses_completion_status') - def test_revoke_access_success(self, mock_get_courses_completion_status): - mock_get_courses_completion_status.return_value = ([], False) - enrollment = CourseEnrollmentFactory.create( - user=self.user, - course_id=self.course.id, # pylint: disable=no-member - is_active=True, - mode=CourseMode.VERIFIED - ) - course_entitlement = CourseEntitlementFactory.create(user=self.user, enrollment_course_run=enrollment) - url = reverse(self.REVOKE_VERIFIED_ACCESS_PATH) - - assert course_entitlement.enrollment_course_run is not None - - response = self.client.post( - url, - data={ - "entitlement_uuids": [str(course_entitlement.uuid)], - "lms_user_id": self.user.id - }, - content_type='application/json', - ) - assert response.status_code == 204 - - course_entitlement.refresh_from_db() - enrollment.refresh_from_db() - assert course_entitlement.expired_at is not None - assert course_entitlement.enrollment_course_run is None - assert enrollment.mode == CourseMode.AUDIT - - @patch('common.djangoapps.entitlements.rest_api.v1.views.get_courses_completion_status') - def test_already_completed_course(self, mock_get_courses_completion_status): - enrollment = CourseEnrollmentFactory.create( - user=self.user, - course_id=self.course.id, # pylint: disable=no-member - is_active=True, - mode=CourseMode.VERIFIED - ) - mock_get_courses_completion_status.return_value = ([str(enrollment.course_id)], False) - course_entitlement = CourseEntitlementFactory.create(user=self.user, enrollment_course_run=enrollment) - url = reverse(self.REVOKE_VERIFIED_ACCESS_PATH) - - assert course_entitlement.enrollment_course_run is not None - - response = self.client.post( - url, - data={ - "entitlement_uuids": [str(course_entitlement.uuid)], - "lms_user_id": self.user.id - }, - content_type='application/json', - ) - assert response.status_code == 204 - - course_entitlement.refresh_from_db() - assert course_entitlement.expired_at is None - assert course_entitlement.enrollment_course_run.mode == CourseMode.VERIFIED - - @patch('common.djangoapps.entitlements.rest_api.v1.views.log.info') - def test_revoke_access_invalid_uuid(self, mock_log): - url = reverse(self.REVOKE_VERIFIED_ACCESS_PATH) - entitlement_uuids = [str(uuid4())] - response = self.client.post( - url, - data={ - "entitlement_uuids": entitlement_uuids, - "lms_user_id": self.user.id - }, - content_type='application/json', - ) - - mock_log.assert_called_once_with("B2C_SUBSCRIPTIONS: Entitlements not found for the provided" - " entitlements data: %s and user: %s", - entitlement_uuids, - self.user.id) - assert response.status_code == 204 - - def test_revoke_access_unauthorized_user(self): - user = UserFactory(is_staff=True, username='not_subscriptions_worker') - self.client.login(username=user.username, password=TEST_PASSWORD) - - enrollment = CourseEnrollmentFactory.create( - user=self.user, - course_id=self.course.id, # pylint: disable=no-member - is_active=True, - mode=CourseMode.VERIFIED - ) - course_entitlement = CourseEntitlementFactory.create(user=self.user, enrollment_course_run=enrollment) - url = reverse(self.REVOKE_VERIFIED_ACCESS_PATH) - - assert course_entitlement.enrollment_course_run is not None - - response = self.client.post( - url, - data={ - "entitlement_uuids": [], - "lms_user_id": self.user.id - }, - content_type='application/json', - ) - assert response.status_code == 403 - - course_entitlement.refresh_from_db() - assert course_entitlement.expired_at is None - assert course_entitlement.enrollment_course_run.mode == CourseMode.VERIFIED - - @patch('common.djangoapps.entitlements.tasks.retry_revoke_subscriptions_verified_access.apply_async') - @patch('common.djangoapps.entitlements.rest_api.v1.views.get_courses_completion_status') - def test_course_completion_exception_triggers_task(self, mock_get_courses_completion_status, mock_task): - mock_get_courses_completion_status.return_value = ([], True) - enrollment = CourseEnrollmentFactory.create( - user=self.user, - course_id=self.course.id, # pylint: disable=no-member - is_active=True, - mode=CourseMode.VERIFIED - ) - course_entitlement = CourseEntitlementFactory.create(user=self.user, enrollment_course_run=enrollment) - - url = reverse(self.REVOKE_VERIFIED_ACCESS_PATH) - - response = self.client.post( - url, - data={ - "entitlement_uuids": [str(course_entitlement.uuid)], - "lms_user_id": self.user.id - }, - content_type='application/json', - ) - assert response.status_code == 204 - mock_task.assert_called_once_with(args=([str(course_entitlement.uuid)], - [str(enrollment.course_id)], - self.user.username)) diff --git a/common/djangoapps/entitlements/rest_api/v1/throttles.py b/common/djangoapps/entitlements/rest_api/v1/throttles.py deleted file mode 100644 index 3a010c76af..0000000000 --- a/common/djangoapps/entitlements/rest_api/v1/throttles.py +++ /dev/null @@ -1,21 +0,0 @@ -""" -Throttle classes for the entitlements API. -""" - -from django.conf import settings -from rest_framework.throttling import UserRateThrottle - - -class ServiceUserThrottle(UserRateThrottle): - """A throttle allowing service users to override rate limiting""" - - def allow_request(self, request, view): - """Returns True if the request is coming from one of the service users - and defaults to UserRateThrottle's configured setting otherwise. - """ - service_users = [ - settings.SUBSCRIPTIONS_SERVICE_WORKER_USERNAME - ] - if request.user.username in service_users: - return True - return super().allow_request(request, view) diff --git a/common/djangoapps/entitlements/rest_api/v1/urls.py b/common/djangoapps/entitlements/rest_api/v1/urls.py index e1d98a2485..e04341b5ef 100644 --- a/common/djangoapps/entitlements/rest_api/v1/urls.py +++ b/common/djangoapps/entitlements/rest_api/v1/urls.py @@ -6,7 +6,7 @@ from django.urls import include from django.urls import path, re_path from rest_framework.routers import DefaultRouter -from .views import EntitlementEnrollmentViewSet, EntitlementViewSet, SubscriptionsRevokeVerifiedAccessView +from .views import EntitlementEnrollmentViewSet, EntitlementViewSet router = DefaultRouter() router.register(r'entitlements', EntitlementViewSet, basename='entitlements') @@ -24,9 +24,4 @@ urlpatterns = [ ENROLLMENTS_VIEW, name='enrollments' ), - path( - 'subscriptions/entitlements/revoke', - SubscriptionsRevokeVerifiedAccessView.as_view(), - name='revoke_subscriptions_verified_access' - ) ] diff --git a/common/djangoapps/entitlements/rest_api/v1/views.py b/common/djangoapps/entitlements/rest_api/v1/views.py index 3306604d5d..4f3dd54b52 100644 --- a/common/djangoapps/entitlements/rest_api/v1/views.py +++ b/common/djangoapps/entitlements/rest_api/v1/views.py @@ -15,7 +15,6 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from rest_framework import permissions, status, viewsets from rest_framework.response import Response -from rest_framework.views import APIView from common.djangoapps.course_modes.models import CourseMode from common.djangoapps.entitlements.models import ( # lint-amnesty, pylint: disable=line-too-long @@ -24,22 +23,13 @@ from common.djangoapps.entitlements.models import ( # lint-amnesty, pylint: dis CourseEntitlementSupportDetail ) from common.djangoapps.entitlements.rest_api.v1.filters import CourseEntitlementFilter -from common.djangoapps.entitlements.rest_api.v1.permissions import ( - IsAdminOrSupportOrAuthenticatedReadOnly, - IsSubscriptionWorkerUser -) +from common.djangoapps.entitlements.rest_api.v1.permissions import IsAdminOrSupportOrAuthenticatedReadOnly from common.djangoapps.entitlements.rest_api.v1.serializers import CourseEntitlementSerializer -from common.djangoapps.entitlements.rest_api.v1.throttles import ServiceUserThrottle -from common.djangoapps.entitlements.tasks import retry_revoke_subscriptions_verified_access -from common.djangoapps.entitlements.utils import ( - is_course_run_entitlement_fulfillable, - revoke_entitlements_and_downgrade_courses_to_audit -) +from common.djangoapps.entitlements.utils import is_course_run_entitlement_fulfillable from common.djangoapps.student.models import AlreadyEnrolledError, CourseEnrollment, CourseEnrollmentException from openedx.core.djangoapps.catalog.utils import get_course_runs_for_course, get_owners_for_course from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from openedx.core.djangoapps.cors_csrf.authentication import SessionAuthenticationCrossDomainCsrf -from openedx.core.djangoapps.credentials.utils import get_courses_completion_status from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in User = get_user_model() @@ -132,7 +122,6 @@ class EntitlementViewSet(viewsets.ModelViewSet): filter_backends = (DjangoFilterBackend,) filterset_class = CourseEntitlementFilter pagination_class = EntitlementsPagination - throttle_classes = (ServiceUserThrottle,) def get_queryset(self): user = self.request.user @@ -530,68 +519,3 @@ class EntitlementEnrollmentViewSet(viewsets.GenericViewSet): }) return Response(status=status.HTTP_204_NO_CONTENT) - - -class SubscriptionsRevokeVerifiedAccessView(APIView): - """ - Endpoint for expiring entitlements for a user and downgrading the enrollments - to Audit mode. This endpoint accepts a list of entitlement UUIDs and will expire - the entitlements along with downgrading the related enrollments to Audit mode. - Only those enrollments are downgraded to Audit for which user has not been awarded - a completion certificate yet. - """ - authentication_classes = (JwtAuthentication, SessionAuthenticationCrossDomainCsrf,) - permission_classes = (permissions.IsAuthenticated, IsSubscriptionWorkerUser,) - throttle_classes = (ServiceUserThrottle,) - - def _process_revoke_and_downgrade_to_audit(self, course_entitlements, user_id, revocable_entitlement_uuids): - """ - Gets course completion status for the provided course entitlements and triggers the - revoke and downgrade to audit process for the course entitlements which are not completed. - Triggers the retry task asynchronously if there is an exception while getting the - course completion status. - """ - entitled_course_ids = [] - user = User.objects.get(id=user_id) - username = user.username - for course_entitlement in course_entitlements: - if course_entitlement.enrollment_course_run is not None: - entitled_course_ids.append(str(course_entitlement.enrollment_course_run.course_id)) - - log.info('B2C_SUBSCRIPTIONS: Getting course completion status for user [%s] and entitled_course_ids %s', - username, - entitled_course_ids) - awarded_cert_course_ids, is_exception = get_courses_completion_status(username, entitled_course_ids) - - if is_exception: - # Trigger the retry task asynchronously - log.exception('B2C_SUBSCRIPTIONS: Exception occurred while getting course completion status for user %s ' - 'and entitled_course_ids %s', - username, - entitled_course_ids) - retry_revoke_subscriptions_verified_access.apply_async(args=(revocable_entitlement_uuids, - entitled_course_ids, - username)) - return - revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, username, awarded_cert_course_ids, - revocable_entitlement_uuids) - - def post(self, request): - """ - Invokes the entitlements expiration process for the provided uuids and downgrades the - enrollments to Audit mode. - """ - revocable_entitlement_uuids = request.data.get('entitlement_uuids', []) - user_id = request.data.get('lms_user_id', None) - course_entitlements = (CourseEntitlement.objects.filter(uuid__in=revocable_entitlement_uuids). - select_related('user'). - select_related('enrollment_course_run')) - - if course_entitlements.exists(): - self._process_revoke_and_downgrade_to_audit(course_entitlements, user_id, revocable_entitlement_uuids) - return Response(status=status.HTTP_204_NO_CONTENT) - else: - log.info('B2C_SUBSCRIPTIONS: Entitlements not found for the provided entitlements data: %s and user: %s', - revocable_entitlement_uuids, - user_id) - return Response(status=status.HTTP_204_NO_CONTENT) diff --git a/common/djangoapps/entitlements/tasks.py b/common/djangoapps/entitlements/tasks.py index 981879e217..9bd200bc90 100644 --- a/common/djangoapps/entitlements/tasks.py +++ b/common/djangoapps/entitlements/tasks.py @@ -4,15 +4,12 @@ This file contains celery tasks for entitlements-related functionality. import logging from celery import shared_task -from celery.exceptions import MaxRetriesExceededError from celery.utils.log import get_task_logger from django.conf import settings # lint-amnesty, pylint: disable=unused-import from django.contrib.auth import get_user_model from edx_django_utils.monitoring import set_code_owner_attribute from common.djangoapps.entitlements.models import CourseEntitlement, CourseEntitlementSupportDetail -from common.djangoapps.entitlements.utils import revoke_entitlements_and_downgrade_courses_to_audit -from openedx.core.djangoapps.credentials.utils import get_courses_completion_status LOGGER = get_task_logger(__name__) log = logging.getLogger(__name__) @@ -154,40 +151,3 @@ def expire_and_create_entitlements(self, entitlement_ids, support_username): '%d entries, task id :%s', len(entitlement_ids), self.request.id) - - -@shared_task(bind=True) -@set_code_owner_attribute -def retry_revoke_subscriptions_verified_access(self, revocable_entitlement_uuids, entitled_course_ids, username): - """ - Task to process course access revoke and move to audit. - This is called only if call to get_courses_completion_status fails due to any exception. - """ - LOGGER.info("B2C_SUBSCRIPTIONS: Running retry_revoke_subscriptions_verified_access for user [%s]," - " entitlement_uuids %s and entitled_course_ids %s", - username, - revocable_entitlement_uuids, - entitled_course_ids) - course_entitlements = CourseEntitlement.objects.filter(uuid__in=revocable_entitlement_uuids) - course_entitlements = course_entitlements.select_related('user').select_related('enrollment_course_run') - if course_entitlements.exists(): - awarded_cert_course_ids, is_exception = get_courses_completion_status(username, entitled_course_ids) - if is_exception: - try: - countdown = 2 ** self.request.retries - self.retry(countdown=countdown, max_retries=3) - except MaxRetriesExceededError: - LOGGER.exception( - 'B2C_SUBSCRIPTIONS: Failed to process retry_revoke_subscriptions_verified_access ' - 'for user [%s] and entitlement_uuids %s', - username, - revocable_entitlement_uuids - ) - return - revoke_entitlements_and_downgrade_courses_to_audit(course_entitlements, username, awarded_cert_course_ids, - revocable_entitlement_uuids) - else: - LOGGER.info('B2C_SUBSCRIPTIONS: Entitlements not found for the provided entitlements uuids %s ' - 'for user [%s] duing the retry_revoke_subscriptions_verified_access task', - revocable_entitlement_uuids, - username) diff --git a/docs/lms-openapi.yaml b/docs/lms-openapi.yaml index 9fa03436e1..5e9afcc6d3 100644 --- a/docs/lms-openapi.yaml +++ b/docs/lms-openapi.yaml @@ -5277,19 +5277,6 @@ paths: required: true type: string format: uuid - /entitlements/v1/subscriptions/entitlements/revoke: - post: - operationId: entitlements_v1_subscriptions_entitlements_revoke_create - description: |- - Invokes the entitlements expiration process for the provided uuids and downgrades the - enrollments to Audit mode. - parameters: [] - responses: - '201': - description: '' - tags: - - entitlements - parameters: [] /experiments/v0/custom/REV-934/: get: operationId: experiments_v0_custom_REV-934_list diff --git a/lms/djangoapps/learner_dashboard/config/waffle.py b/lms/djangoapps/learner_dashboard/config/waffle.py index 2195a26972..cc63e8d5d1 100644 --- a/lms/djangoapps/learner_dashboard/config/waffle.py +++ b/lms/djangoapps/learner_dashboard/config/waffle.py @@ -37,20 +37,3 @@ ENABLE_MASTERS_PROGRAM_TAB_VIEW = WaffleFlag( 'learner_dashboard.enable_masters_program_tab_view', __name__, ) - -# .. toggle_name: learner_dashboard.enable_b2c_subscriptions -# .. toggle_implementation: WaffleFlag -# .. toggle_default: False -# .. toggle_description: Waffle flag to enable new B2C Subscriptions Program data. -# This flag is used to decide whether we need to enable program subscription related properties in program listing -# and detail pages. -# .. toggle_use_cases: temporary -# .. toggle_creation_date: 2023-04-13 -# .. toggle_target_removal_date: 2023-07-01 -# .. toggle_warning: When the flag is ON, the new B2C Subscriptions Program data will be enabled in program listing -# and detail pages. -# .. toggle_tickets: PON-79 -ENABLE_B2C_SUBSCRIPTIONS = WaffleFlag( - 'learner_dashboard.enable_b2c_subscriptions', - __name__, -) diff --git a/lms/djangoapps/learner_dashboard/programs.py b/lms/djangoapps/learner_dashboard/programs.py index d567a4b9a3..dc334c0ce3 100644 --- a/lms/djangoapps/learner_dashboard/programs.py +++ b/lms/djangoapps/learner_dashboard/programs.py @@ -6,7 +6,6 @@ import json from abc import ABC, abstractmethod from urllib.parse import quote -from django.conf import settings from django.contrib.sites.shortcuts import get_current_site from django.http import Http404 from django.template.loader import render_to_string @@ -18,7 +17,7 @@ from web_fragments.fragment import Fragment from common.djangoapps.student.models import anonymous_id_for_user from common.djangoapps.student.roles import GlobalStaff -from lms.djangoapps.learner_dashboard.utils import b2c_subscriptions_enabled, program_tab_view_is_enabled +from lms.djangoapps.learner_dashboard.utils import program_tab_view_is_enabled from openedx.core.djangoapps.catalog.utils import get_programs from openedx.core.djangoapps.plugin_api.views import EdxFragmentView from openedx.core.djangoapps.programs.models import ( @@ -32,9 +31,7 @@ from openedx.core.djangoapps.programs.utils import ( get_industry_and_credit_pathways, get_program_and_course_data, get_program_marketing_url, - get_program_subscriptions_marketing_url, get_program_urls, - get_programs_subscription_data ) from openedx.core.djangoapps.user_api.preferences.api import get_user_preferences from openedx.core.djangolib.markup import HTML @@ -60,30 +57,12 @@ class ProgramsFragmentView(EdxFragmentView): raise Http404 meter = ProgramProgressMeter(request.site, user, mobile_only=mobile_only) - is_user_b2c_subscriptions_enabled = b2c_subscriptions_enabled(mobile_only) - programs_subscription_data = ( - get_programs_subscription_data(user) - if is_user_b2c_subscriptions_enabled - else [] - ) - subscription_upsell_data = ( - { - 'marketing_url': get_program_subscriptions_marketing_url(), - 'minimum_price': settings.SUBSCRIPTIONS_MINIMUM_PRICE, - 'trial_length': settings.SUBSCRIPTIONS_TRIAL_LENGTH, - } - if is_user_b2c_subscriptions_enabled - else {} - ) context = { 'marketing_url': get_program_marketing_url(programs_config, mobile_only), 'programs': meter.engaged_programs, 'progress': meter.progress(), - 'programs_subscription_data': programs_subscription_data, - 'subscription_upsell_data': subscription_upsell_data, 'user_preferences': get_user_preferences(user), - 'is_user_b2c_subscriptions_enabled': is_user_b2c_subscriptions_enabled, 'mobile_only': bool(mobile_only) } html = render_to_string('learner_dashboard/programs_fragment.html', context) @@ -137,12 +116,6 @@ class ProgramDetailsFragmentView(EdxFragmentView): program_discussion_lti = ProgramDiscussionLTI(program_uuid, request) program_live_lti = ProgramLiveLTI(program_uuid, request) - is_user_b2c_subscriptions_enabled = b2c_subscriptions_enabled(mobile_only) - program_subscription_data = ( - get_programs_subscription_data(user, program_uuid) - if is_user_b2c_subscriptions_enabled - else [] - ) def program_tab_view_enabled() -> bool: return program_tab_view_is_enabled() and ( @@ -156,14 +129,11 @@ class ProgramDetailsFragmentView(EdxFragmentView): 'urls': urls, 'user_preferences': get_user_preferences(user), 'program_data': program_data, - 'program_subscription_data': program_subscription_data, 'course_data': course_data, 'certificate_data': certificate_data, 'industry_pathways': industry_pathways, 'credit_pathways': credit_pathways, 'program_tab_view_enabled': program_tab_view_enabled(), - 'is_user_b2c_subscriptions_enabled': is_user_b2c_subscriptions_enabled, - 'subscriptions_trial_length': settings.SUBSCRIPTIONS_TRIAL_LENGTH, 'discussion_fragment': { 'configured': program_discussion_lti.is_configured, 'iframe': program_discussion_lti.render_iframe() diff --git a/lms/djangoapps/learner_dashboard/utils.py b/lms/djangoapps/learner_dashboard/utils.py index a604ba7378..5e9c172fcb 100644 --- a/lms/djangoapps/learner_dashboard/utils.py +++ b/lms/djangoapps/learner_dashboard/utils.py @@ -7,7 +7,6 @@ from opaque_keys.edx.keys import CourseKey from common.djangoapps.student.roles import GlobalStaff from lms.djangoapps.learner_dashboard.config.waffle import ( - ENABLE_B2C_SUBSCRIPTIONS, ENABLE_MASTERS_PROGRAM_TAB_VIEW, ENABLE_PROGRAM_TAB_VIEW ) @@ -50,19 +49,3 @@ def is_enrolled_or_staff(request, program_uuid): except ObjectDoesNotExist: return False return True - - -def b2c_subscriptions_is_enabled() -> bool: - """ - Check if B2C program subscriptions flag is enabled. - """ - return ENABLE_B2C_SUBSCRIPTIONS.is_enabled() - - -def b2c_subscriptions_enabled(is_mobile=False) -> bool: - """ - Check whether B2C Subscriptions pages should be shown to user. - """ - if not is_mobile and b2c_subscriptions_is_enabled(): - return True - return False diff --git a/lms/envs/common.py b/lms/envs/common.py index 2d31cba982..a6c8e810d2 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -4691,7 +4691,6 @@ ENTERPRISE_ALL_SERVICE_USERNAMES = [ 'enterprise_channel_worker', 'enterprise_access_worker', 'enterprise_subsidy_worker', - 'subscriptions_worker' ] # Setting for Open API key and prompts used by edx-enterprise. @@ -5385,17 +5384,6 @@ ENTERPRISE_MANUAL_REPORTING_CUSTOMER_UUIDS = [] AVAILABLE_DISCUSSION_TOURS = [] -######################## Subscriptions API SETTINGS ######################## -SUBSCRIPTIONS_ROOT_URL = "" -SUBSCRIPTIONS_API_PATH = f"{SUBSCRIPTIONS_ROOT_URL}/api/v1/stripe-subscription/" - -SUBSCRIPTIONS_LEARNER_HELP_CENTER_URL = None -SUBSCRIPTIONS_BUY_SUBSCRIPTION_URL = f"{SUBSCRIPTIONS_ROOT_URL}/api/v1/stripe-subscribe/" -SUBSCRIPTIONS_MANAGE_SUBSCRIPTION_URL = None -SUBSCRIPTIONS_MINIMUM_PRICE = '$39' -SUBSCRIPTIONS_TRIAL_LENGTH = 7 -SUBSCRIPTIONS_SERVICE_WORKER_USERNAME = 'subscriptions_worker' - ############## NOTIFICATIONS ############## NOTIFICATIONS_EXPIRY = 60 EXPIRED_NOTIFICATIONS_DELETE_BATCH_SIZE = 10000 diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py index 6110179628..890164b0bd 100644 --- a/lms/envs/devstack.py +++ b/lms/envs/devstack.py @@ -522,16 +522,6 @@ course_access_role_removed_event_setting = EVENT_BUS_PRODUCER_CONFIG[ ] course_access_role_removed_event_setting['learning-course-access-role-lifecycle']['enabled'] = True -######################## Subscriptions API SETTINGS ######################## -SUBSCRIPTIONS_ROOT_URL = "http://host.docker.internal:18750" -SUBSCRIPTIONS_API_PATH = f"{SUBSCRIPTIONS_ROOT_URL}/api/v1/stripe-subscription/" - -SUBSCRIPTIONS_LEARNER_HELP_CENTER_URL = None -SUBSCRIPTIONS_BUY_SUBSCRIPTION_URL = f"{SUBSCRIPTIONS_ROOT_URL}/api/v1/stripe-subscribe/" -SUBSCRIPTIONS_MANAGE_SUBSCRIPTION_URL = None -SUBSCRIPTIONS_MINIMUM_PRICE = '$39' -SUBSCRIPTIONS_TRIAL_LENGTH = 7 - # API access management API_ACCESS_MANAGER_EMAIL = 'api-access@example.com' API_ACCESS_FROM_EMAIL = 'api-requests@example.com' diff --git a/lms/envs/test.py b/lms/envs/test.py index 3c4bb95649..a9e8aaf9f2 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -650,15 +650,6 @@ SURVEY_REPORT_CHECK_THRESHOLD = 6 SURVEY_REPORT_ENABLE = True ANONYMOUS_SURVEY_REPORT = False -######################## Subscriptions API SETTINGS ######################## -SUBSCRIPTIONS_ROOT_URL = "http://localhost:18750" -SUBSCRIPTIONS_API_PATH = f"{SUBSCRIPTIONS_ROOT_URL}/api/v1/stripe-subscription/" - -SUBSCRIPTIONS_LEARNER_HELP_CENTER_URL = None -SUBSCRIPTIONS_BUY_SUBSCRIPTION_URL = f"{SUBSCRIPTIONS_ROOT_URL}/api/v1/stripe-subscribe/" -SUBSCRIPTIONS_MANAGE_SUBSCRIPTION_URL = None -SUBSCRIPTIONS_MINIMUM_PRICE = '$39' -SUBSCRIPTIONS_TRIAL_LENGTH = 7 CSRF_TRUSTED_ORIGINS = ['.example.com'] CSRF_TRUSTED_ORIGINS_WITH_SCHEME = ['https://*.example.com'] diff --git a/lms/static/js/learner_dashboard/models/program_subscription_model.js b/lms/static/js/learner_dashboard/models/program_subscription_model.js deleted file mode 100644 index 18f30031f7..0000000000 --- a/lms/static/js/learner_dashboard/models/program_subscription_model.js +++ /dev/null @@ -1,86 +0,0 @@ -import Backbone from 'backbone'; -import moment from 'moment'; - -import DateUtils from 'edx-ui-toolkit/js/utils/date-utils'; -import StringUtils from 'edx-ui-toolkit/js/utils/string-utils'; - - -/** - * Model for Program Subscription Data. - */ -class ProgramSubscriptionModel extends Backbone.Model { - constructor({ context }, ...args) { - const { - subscriptionData: [data = {}], - programData: { subscription_prices }, - urls = {}, - userPreferences = {}, - subscriptionsTrialLength: trialLength = 7, - } = context; - - const priceInUSD = subscription_prices?.find(({ currency }) => currency === 'USD'); - - const subscriptionState = data.subscription_state?.toLowerCase() ?? ''; - const subscriptionPrice = StringUtils.interpolate( - gettext('${price}/month {currency}'), - { - price: parseFloat(priceInUSD?.price), - currency: priceInUSD?.currency, - } - ); - - const subscriptionUrl = - subscriptionState === 'active' - ? urls.manage_subscription_url - : urls.buy_subscription_url; - - const hasActiveTrial = false; - - const remainingDays = 0; - - const [currentPeriodEnd] = ProgramSubscriptionModel.formatDate( - data.current_period_end, - userPreferences - ); - const [trialEndDate, trialEndTime] = ['', '']; - - super( - { - hasActiveTrial, - currentPeriodEnd, - remainingDays, - subscriptionPrice, - subscriptionState, - subscriptionUrl, - trialEndDate, - trialEndTime, - trialLength, - }, - ...args - ); - } - - static formatDate(date, userPreferences) { - if (!date) { - return ['', '']; - } - - const userTimezone = ( - userPreferences.time_zone || moment?.tz?.guess?.() || 'UTC' - ); - const userLanguage = userPreferences['pref-lang'] || 'en'; - const context = { - datetime: date, - timezone: userTimezone, - language: userLanguage, - format: DateUtils.dateFormatEnum.shortDate, - }; - - const localDate = DateUtils.localize(context); - const localTime = ''; - - return [localDate, localTime]; - } -} - -export default ProgramSubscriptionModel; diff --git a/lms/static/js/learner_dashboard/program_list_factory.js b/lms/static/js/learner_dashboard/program_list_factory.js index 5433306641..b9ff1c4019 100644 --- a/lms/static/js/learner_dashboard/program_list_factory.js +++ b/lms/static/js/learner_dashboard/program_list_factory.js @@ -11,58 +11,18 @@ import HeaderView from './views/program_list_header_view'; function ProgramListFactory(options) { const progressCollection = new ProgressCollection(); - const subscriptionCollection = new Backbone.Collection(); if (options.userProgress) { progressCollection.set(options.userProgress); options.progressCollection = progressCollection; // eslint-disable-line no-param-reassign } - if (options.programsSubscriptionData.length) { - subscriptionCollection.set(options.programsSubscriptionData); - options.subscriptionCollection = subscriptionCollection; // eslint-disable-line no-param-reassign - } - if (options.programsData.length) { if (!options.mobileOnly) { new HeaderView({ context: options, }).render(); } - - const activeSubscriptions = options.programsSubscriptionData - // eslint-disable-next-line camelcase - .filter(({ subscription_state }) => subscription_state === 'active') - .sort((a, b) => new Date(b.created) - new Date(a.created)); - - // Sort programs so programs with active subscriptions are at the top - if (activeSubscriptions.length) { - // eslint-disable-next-line no-param-reassign - options.programsData = options.programsData - .map((programsData) => ({ - ...programsData, - subscriptionIndex: activeSubscriptions.findIndex( - // eslint-disable-next-line camelcase - ({ resource_id }) => resource_id === programsData.uuid, - ), - })) - .sort(({ subscriptionIndex: indexA }, { subscriptionIndex: indexB }) => { - switch (true) { - case indexA === -1 && indexB === -1: - // Maintain the original order for non-subscription programs - return 0; - case indexA === -1: - // Move non-subscription program to the end - return 1; - case indexB === -1: - // Keep non-subscription program to the end - return -1; - default: - // Sort by subscriptionIndex in ascending order - return indexA - indexB; - } - }); - } } new CollectionListView({ diff --git a/lms/static/js/learner_dashboard/spec/collection_list_view_spec.js b/lms/static/js/learner_dashboard/spec/collection_list_view_spec.js index c9c1c4d97b..1cd490447b 100644 --- a/lms/static/js/learner_dashboard/spec/collection_list_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/collection_list_view_spec.js @@ -1,7 +1,5 @@ /* globals setFixtures */ -import Backbone from 'backbone'; - import CollectionListView from '../views/collection_list_view'; import ProgramCardView from '../views/program_card_view'; import ProgramCollection from '../collections/program_collection'; @@ -11,7 +9,6 @@ describe('Collection List View', () => { let view = null; let programCollection; let progressCollection; - let subscriptionCollection; const context = { programsData: [ { @@ -101,21 +98,14 @@ describe('Collection List View', () => { not_started: 3, }, ], - programsSubscriptionData: [{ - resource_id: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8', - subscription_state: 'active', - }], - isUserB2CSubscriptionsEnabled: false, }; beforeEach(() => { setFixtures('
'); programCollection = new ProgramCollection(context.programsData); progressCollection = new ProgressCollection(); - subscriptionCollection = new Backbone.Collection(context.programsSubscriptionData); progressCollection.set(context.userProgress); context.progressCollection = progressCollection; - context.subscriptionCollection = subscriptionCollection; view = new CollectionListView({ el: '.program-cards-container', diff --git a/lms/static/js/learner_dashboard/spec/course_card_view_spec.js b/lms/static/js/learner_dashboard/spec/course_card_view_spec.js index 5a0f181628..91439c4a87 100644 --- a/lms/static/js/learner_dashboard/spec/course_card_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/course_card_view_spec.js @@ -17,10 +17,8 @@ describe('Course Card View', () => { programData, collectionCourseStatus, courseData: {}, - subscriptionData: [], urls: {}, userPreferences: {}, - isSubscriptionEligible: false, }; if (typeof collectionCourseStatus === 'undefined') { diff --git a/lms/static/js/learner_dashboard/spec/program_alert_list_view_spec.js b/lms/static/js/learner_dashboard/spec/program_alert_list_view_spec.js deleted file mode 100644 index 501cb90004..0000000000 --- a/lms/static/js/learner_dashboard/spec/program_alert_list_view_spec.js +++ /dev/null @@ -1,58 +0,0 @@ -/* globals setFixtures */ - -import ProgramAlertListView from '../views/program_alert_list_view'; - -describe('Program Alert List View', () => { - let view = null; - const context = { - enrollmentAlerts: [{ title: 'Test Program' }], - trialEndingAlerts: [{ - title: 'Test Program', - hasActiveTrial: true, - currentPeriodEnd: 'May 8, 2023', - remainingDays: 2, - subscriptionPrice: '$100/month USD', - subscriptionState: 'active', - subscriptionUrl: null, - trialEndDate: 'Apr 20, 2023', - trialEndTime: '5:59 am', - trialLength: 7, - }], - pageType: 'programDetails', - }; - - beforeEach(() => { - setFixtures('
'); - view = new ProgramAlertListView({ - el: '.js-program-details-alerts', - context, - }); - view.render(); - }); - - afterEach(() => { - view.remove(); - }); - - it('should exist', () => { - expect(view).toBeDefined(); - }); - - it('should render no enrollement alert', () => { - expect(view.$('.alert:first .alert-heading').text().trim()).toEqual( - 'Enroll in a Test Program\'s course', - ); - expect(view.$('.alert:first .alert-message').text().trim()).toEqual( - 'You have an active subscription to the Test Program program but are not enrolled in any courses. Enroll in a remaining course and enjoy verified access.', - ); - }); - - it('should render subscription trial is expiring alert', () => { - expect(view.$('.alert:last .alert-heading').text().trim()).toEqual( - 'Subscription trial expires in 2 days', - ); - expect(view.$('.alert:last .alert-message').text().trim()).toEqual( - 'Your Test Program trial will expire in 2 days at 5:59 am on Apr 20, 2023 and the card on file will be charged $100/month USD.', - ); - }); -}); diff --git a/lms/static/js/learner_dashboard/spec/program_card_view_spec.js b/lms/static/js/learner_dashboard/spec/program_card_view_spec.js index 290db60a4d..bf8a718f0a 100644 --- a/lms/static/js/learner_dashboard/spec/program_card_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/program_card_view_spec.js @@ -42,7 +42,6 @@ describe('Program card View', () => { name: 'Wageningen University & Research', }, ], - subscriptionIndex: 1, }; const userProgress = [ { @@ -58,11 +57,6 @@ describe('Program card View', () => { not_started: 3, }, ]; - // eslint-disable-next-line no-undef - const subscriptionCollection = new Backbone.Collection([{ - resource_id: 'a87e5eac-3c93-45a1-a8e1-4c79ca8401c8', - subscription_state: 'active', - }]); const progressCollection = new ProgressCollection(); const cardRenders = ($card) => { expect($card).toBeDefined(); @@ -80,8 +74,6 @@ describe('Program card View', () => { model: programModel, context: { progressCollection, - subscriptionCollection, - isUserB2CSubscriptionsEnabled: true, }, }); }); @@ -133,10 +125,6 @@ describe('Program card View', () => { view.remove(); view = new ProgramCardView({ model: programModel, - context: { - subscriptionCollection, - isUserB2CSubscriptionsEnabled: true, - }, }); cardRenders(view.$el); expect(view.$('.progress').length).toEqual(0); @@ -149,10 +137,6 @@ describe('Program card View', () => { programModel = new ProgramModel(programNoBanner); view = new ProgramCardView({ model: programModel, - context: { - subscriptionCollection, - isUserB2CSubscriptionsEnabled: true, - }, }); cardRenders(view.$el); expect(view.$el.find('.banner-image').attr('srcset')).toEqual(''); @@ -167,16 +151,8 @@ describe('Program card View', () => { programModel = new ProgramModel(programNoBanner); view = new ProgramCardView({ model: programModel, - context: { - subscriptionCollection, - isUserB2CSubscriptionsEnabled: true, - }, }); cardRenders(view.$el); expect(view.$el.find('.banner-image').attr('srcset')).toEqual(''); }); - - it('should render the subscription badge if subscription is active', () => { - expect(view.$('.subscription-badge .badge').html()?.trim()).toEqual('Subscribed'); - }); }); diff --git a/lms/static/js/learner_dashboard/spec/program_details_header_spec.js b/lms/static/js/learner_dashboard/spec/program_details_header_spec.js index d28d8f0bd3..862fb3f228 100644 --- a/lms/static/js/learner_dashboard/spec/program_details_header_spec.js +++ b/lms/static/js/learner_dashboard/spec/program_details_header_spec.js @@ -45,16 +45,6 @@ describe('Program Details Header View', () => { }, ], }, - subscriptionData: [ - { - trial_end: '1970-01-01T03:25:45Z', - current_period_end: '1970-06-03T07:12:04Z', - price: '100.00', - currency: 'USD', - subscription_state: 'active', - }, - ], - isSubscriptionEligible: true, }; beforeEach(() => { @@ -81,8 +71,4 @@ describe('Program Details Header View', () => { expect(view.$('.org-logo').attr('alt')) .toEqual(`${context.programData.authoring_organizations[0].name}'s logo`); }); - - it('should render the subscription badge if subscription is active', () => { - expect(view.$('.meta-info .badge').html().trim()).toEqual('Subscribed'); - }); }); diff --git a/lms/static/js/learner_dashboard/spec/program_details_sidebar_view_spec.js b/lms/static/js/learner_dashboard/spec/program_details_sidebar_view_spec.js index 60c877da8a..e1db3ddd18 100644 --- a/lms/static/js/learner_dashboard/spec/program_details_sidebar_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/program_details_sidebar_view_spec.js @@ -1,9 +1,7 @@ /* globals setFixtures */ import Backbone from 'backbone'; -import moment from 'moment'; -import SubscriptionModel from '../models/program_subscription_model'; import ProgramSidebarView from '../views/program_details_sidebar_view'; describe('Program Progress View', () => { @@ -25,15 +23,13 @@ describe('Program Progress View', () => { "url": "/certificates/bed3980e67ca40f0b31e309d9dfe9e7e", "type": "course", "title": "Introduction to the Treatment of Urban Sewage" } ], - urls: {"program_listing_url": "/dashboard/programs/", "commerce_api_url": "/api/commerce/v0/baskets/", "track_selection_url": "/course_modes/choose/", "program_record_url": "/foo/bar", "buy_subscription_url": "/subscriptions", "orders_and_subscriptions_url": "/orders", "subscriptions_learner_help_center_url": "/learner"}, + urls: {"program_listing_url": "/dashboard/programs/", "commerce_api_url": "/api/commerce/v0/baskets/", "track_selection_url": "/course_modes/choose/"}, userPreferences: {"pref-lang": "en"} }; /* eslint-enable */ let programModel; let courseData; - let subscriptionData; let certificateCollection; - let isSubscriptionEligible; const testCircle = (progress) => { const $circle = view.$('.progress-circle'); @@ -53,55 +49,15 @@ describe('Program Progress View', () => { expect(parseInt($numbers.find('.total').html(), 10)).toEqual(total); }; - const testSubscriptionState = (state, heading, body) => { - isSubscriptionEligible = true; - subscriptionData.subscription_state = state; - // eslint-disable-next-line no-use-before-define - view = initView(); - // eslint-disable-next-line no-param-reassign - body += ' on the Orders and subscriptions page'; - - expect(view.$('.js-subscription-info')[0]).toBeInDOM(); - expect( - view.$('.js-subscription-info .divider-heading').text().trim(), - ).toEqual(heading); - expect( - view.$('.js-subscription-info .subscription-section p:nth-child(1)'), - ).toContainHtml(body); - expect( - view.$('.js-subscription-info .subscription-section p:nth-child(2)'), - ).toContainText( - /Need help\? Check out the.*Learner Help Center.*to troubleshoot issues or contact support/, - ); - expect( - view.$('.js-subscription-info .subscription-section p:nth-child(2) .subscription-link').attr('href'), - ).toEqual('/learner'); - }; - const initView = () => new ProgramSidebarView({ el: '.js-program-sidebar', model: programModel, courseModel: courseData, - subscriptionModel: new SubscriptionModel({ - context: { - programData: { - subscription_eligible: isSubscriptionEligible, - subscription_prices: [{ - price: '100.00', - currency: 'USD', - }], - }, - subscriptionData: [subscriptionData], - urls: data.urls, - userPreferences: data.userPreferences, - }, - }), certificateCollection, industryPathways: data.industryPathways, creditPathways: data.creditPathways, programTabViewEnabled: false, urls: data.urls, - isSubscriptionEligible, }); beforeEach(() => { @@ -109,14 +65,6 @@ describe('Program Progress View', () => { programModel = new Backbone.Model(data.programData); courseData = new Backbone.Model(data.courseData); certificateCollection = new Backbone.Collection(data.certificateData); - isSubscriptionEligible = false; - subscriptionData = { - trial_end: '1970-01-01T03:25:45Z', - current_period_end: '1970-06-03T07:12:04Z', - price: '100.00', - currency: 'USD', - subscription_state: 'pre', - }; }); afterEach(() => { @@ -203,69 +151,14 @@ describe('Program Progress View', () => { el: '.js-program-sidebar', model: programModel, courseModel: courseData, - subscriptionModel: new SubscriptionModel({ - context: { - programData: { - subscription_eligible: isSubscriptionEligible, - subscription_prices: [{ - price: '100.00', - currency: 'USD', - }], - }, - subscriptionData: [subscriptionData], - urls: data.urls, - userPreferences: data.userPreferences, - }, - }), certificateCollection, industryPathways: [], creditPathways: [], programTabViewEnabled: false, urls: data.urls, - isSubscriptionEligible, }); expect(emptyView.$('.program-credit-pathways .divider-heading')).toHaveLength(0); expect(emptyView.$('.program-industry-pathways .divider-heading')).toHaveLength(0); }); - - it('should not render subscription info if program is not subscription eligible', () => { - view = initView(); - expect(view.$('.js-subscription-info')[0]).not.toBeInDOM(); - }); - - it('should render subscription info if program is subscription eligible', () => { - testSubscriptionState( - 'pre', - 'Inactive subscription', - 'If you had a subscription previously, your payment history is still available', - ); - }); - - it('should render active trial subscription info if subscription is active with trial', () => { - subscriptionData.trial_end = moment().add(3, 'days').utc().format( - 'YYYY-MM-DDTHH:mm:ss[Z]', - ); - testSubscriptionState( - 'active', - 'Trial subscription', - 'View your receipts or modify your subscription', - ); - }); - - it('should render active subscription info if subscription active', () => { - testSubscriptionState( - 'active', - 'Active subscription', - 'View your receipts or modify your subscription', - ); - }); - - it('should render inactive subscription info if subscription inactive', () => { - testSubscriptionState( - 'inactive', - 'Inactive subscription', - 'Restart your subscription for $100/month USD. Your payment history is still available', - ); - }); }); diff --git a/lms/static/js/learner_dashboard/spec/program_details_view_spec.js b/lms/static/js/learner_dashboard/spec/program_details_view_spec.js index feaf725261..a3be0f1081 100644 --- a/lms/static/js/learner_dashboard/spec/program_details_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/program_details_view_spec.js @@ -7,11 +7,6 @@ describe('Program Details View', () => { let view = null; const options = { programData: { - subscription_eligible: false, - subscription_prices: [{ - price: '100.00', - currency: 'USD', - }], subtitle: '', overview: '', weeks_to_complete: null, @@ -468,24 +463,11 @@ describe('Program Details View', () => { }, ], }, - subscriptionData: [ - { - trial_end: '1970-01-01T03:25:45Z', - current_period_end: '1970-06-03T07:12:04Z', - price: '100.00', - currency: 'USD', - subscription_state: 'pre', - }, - ], urls: { program_listing_url: '/dashboard/programs/', commerce_api_url: '/api/commerce/v0/baskets/', track_selection_url: '/course_modes/choose/', program_record_url: 'http://credentials.example.com/records/programs/UUID', - buy_subscription_url: '/subscriptions', - manage_subscription_url: '/orders', - subscriptions_learner_help_center_url: '/learner', - orders_and_subscriptions_url: '/orders', }, userPreferences: { 'pref-lang': 'en', @@ -513,59 +495,9 @@ describe('Program Details View', () => { }, ], programTabViewEnabled: false, - isUserB2CSubscriptionsEnabled: false, }; const data = options.programData; - const testSubscriptionState = (state, heading, body, trial = false) => { - const subscriptionData = { - ...options.subscriptionData[0], - subscription_state: state, - }; - if (trial) { - subscriptionData.trial_end = moment().add(3, 'days').utc().format( - 'YYYY-MM-DDTHH:mm:ss[Z]', - ); - } - // eslint-disable-next-line no-use-before-define - view = initView({ - // eslint-disable-next-line no-undef - programData: $.extend({}, options.programData, { - subscription_eligible: true, - }), - isUserB2CSubscriptionsEnabled: true, - subscriptionData: [subscriptionData], - }); - view.render(); - expect(view.$('.upgrade-subscription')[0]).toBeInDOM(); - expect(view.$('.upgrade-subscription .upgrade-button')) - .toContainText(heading); - expect(view.$('.upgrade-subscription .subscription-info-brief')) - .toContainText(body); - }; - - const testSubscriptionSunsetting = (state, heading, body) => { - const subscriptionData = { - ...options.subscriptionData[0], - subscription_state: state, - }; - // eslint-disable-next-line no-use-before-define - view = initView({ - // eslint-disable-next-line no-undef - programData: $.extend({}, options.programData, { - subscription_eligible: false, - }), - isUserB2CSubscriptionsEnabled: true, - subscriptionData: [subscriptionData], - }); - view.render(); - expect(view.$('.upgrade-subscription')[0]).not.toBeInDOM(); - expect(view.$('.upgrade-subscription .upgrade-button')).not - .toContainText(heading); - expect(view.$('.upgrade-subscription .subscription-info-brief')).not - .toContainText(body); - }; - const initView = (updates) => { // eslint-disable-next-line no-undef const viewOptions = $.extend({}, options, updates); @@ -730,37 +662,4 @@ describe('Program Details View', () => { properties, ); }); - - it('should not render the get subscription link if program is not active', () => { - testSubscriptionSunsetting( - 'pre', - 'Start 7-day free trial', - '$100/month USD subscription after trial ends. Cancel anytime.', - ); - }); - - it('should not render appropriate subscription text when subscription is active with trial', () => { - testSubscriptionSunsetting( - 'active', - 'Manage my subscription', - 'Trial ends', - true, - ); - }); - - it('should not render appropriate subscription text when subscription is active', () => { - testSubscriptionSunsetting( - 'active', - 'Manage my subscription', - 'Your next billing date is', - ); - }); - - it('should not render appropriate subscription text when subscription is inactive', () => { - testSubscriptionSunsetting( - 'inactive', - 'Restart my subscription', - '$100/month USD subscription. Cancel anytime.', - ); - }); }); diff --git a/lms/static/js/learner_dashboard/spec/program_list_header_view_spec.js b/lms/static/js/learner_dashboard/spec/program_list_header_view_spec.js index 4a663fc1f8..5e1c09bfe4 100644 --- a/lms/static/js/learner_dashboard/spec/program_list_header_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/program_list_header_view_spec.js @@ -13,27 +13,14 @@ describe('Program List Header View', () => { { uuid: '5b234e3c-3a2e-472e-90db-6f51501dc86c', title: 'edX Demonstration Program', - subscription_eligible: null, - subscription_prices: [], detail_url: '/dashboard/programs/5b234e3c-3a2e-472e-90db-6f51501dc86c/', }, { uuid: 'b90d70d5-f981-4508-bdeb-5b792d930c03', title: 'Test Program', - subscription_eligible: true, - subscription_prices: [{ price: '500.00', currency: 'USD' }], detail_url: '/dashboard/programs/b90d70d5-f981-4508-bdeb-5b792d930c03/', }, ], - programsSubscriptionData: [ - { - id: 'eeb25640-9741-4c11-963c-8a27337f217c', - resource_id: 'b90d70d5-f981-4508-bdeb-5b792d930c03', - trial_end: '2022-04-20T05:59:42Z', - current_period_end: '2023-05-08T05:59:42Z', - subscription_state: 'active', - }, - ], userProgress: [ { uuid: '5b234e3c-3a2e-472e-90db-6f51501dc86c', @@ -50,13 +37,9 @@ describe('Program List Header View', () => { all_unenrolled: true, }, ], - isUserB2CSubscriptionsEnabled: true, }; beforeEach(() => { - context.subscriptionCollection = new Backbone.Collection( - context.programsSubscriptionData, - ); context.progressCollection = new ProgressCollection( context.userProgress, ); @@ -78,18 +61,4 @@ describe('Program List Header View', () => { it('should render the program heading', () => { expect(view.$('h2:first').text().trim()).toEqual('My programs'); }); - - it('should render a program alert', () => { - expect( - view.$('.js-program-list-alerts .alert .alert-heading').html().trim(), - ).toEqual('Enroll in a Test Program\'s course'); - expect( - view.$('.js-program-list-alerts .alert .alert-message'), - ).toContainHtml( - 'According to our records, you are not enrolled in any courses included in your Test Program program subscription. Enroll in a course from the Program Details page.', - ); - expect( - view.$('.js-program-list-alerts .alert .view-button').attr('href'), - ).toEqual('/dashboard/programs/b90d70d5-f981-4508-bdeb-5b792d930c03/'); - }); }); diff --git a/lms/static/js/learner_dashboard/spec/sidebar_view_spec.js b/lms/static/js/learner_dashboard/spec/sidebar_view_spec.js index 04c936908e..e96369abb6 100644 --- a/lms/static/js/learner_dashboard/spec/sidebar_view_spec.js +++ b/lms/static/js/learner_dashboard/spec/sidebar_view_spec.js @@ -6,12 +6,6 @@ describe('Sidebar View', () => { let view = null; const context = { marketingUrl: 'https://www.example.org/programs', - subscriptionUpsellData: { - marketing_url: 'https://www.example.org/program-subscriptions', - minimum_price: '$39', - trial_length: 7, - }, - isUserB2CSubscriptionsEnabled: true, }; beforeEach(() => { @@ -32,10 +26,6 @@ describe('Sidebar View', () => { expect(view).toBeDefined(); }); - it('should not render the subscription upsell section', () => { - expect(view.$('.js-subscription-upsell')[0]).not.toBeInDOM(); - }); - it('should load the exploration panel given a marketing URL', () => { expect(view.$('.program-advertise .advertise-message').html().trim()) .toEqual( @@ -49,10 +39,6 @@ describe('Sidebar View', () => { view.remove(); view = new SidebarView({ el: '.sidebar', - context: { - isUserB2CSubscriptionsEnabled: true, - subscriptionUpsellData: context.subscriptionUpsellData, - }, }); view.render(); const $ad = view.$el.find('.program-advertise'); diff --git a/lms/static/js/learner_dashboard/views/course_card_view.js b/lms/static/js/learner_dashboard/views/course_card_view.js index 72028d6d95..dce9c7a384 100644 --- a/lms/static/js/learner_dashboard/views/course_card_view.js +++ b/lms/static/js/learner_dashboard/views/course_card_view.js @@ -9,8 +9,6 @@ import ExpiredNotificationView from './expired_notification_view'; import CourseEnrollView from './course_enroll_view'; import EntitlementView from './course_entitlement_view'; -import SubscriptionModel from '../models/program_subscription_model'; - import pageTpl from '../../../templates/learner_dashboard/course_card.underscore'; class CourseCardView extends Backbone.View { @@ -27,9 +25,6 @@ class CourseCardView extends Backbone.View { this.enrollModel = new EnrollModel(); if (options.context) { this.urlModel = new Backbone.Model(options.context.urls); - this.subscriptionModel = new SubscriptionModel({ - context: options.context, - }); this.enrollModel.urlRoot = this.urlModel.get('commerce_api_url'); } this.context = options.context || {}; @@ -93,8 +88,6 @@ class CourseCardView extends Backbone.View { this.upgradeMessage = new UpgradeMessageView({ $el: $upgradeMessage, model: this.model, - subscriptionModel: this.subscriptionModel, - isSubscriptionEligible: this.context.isSubscriptionEligible, }); $certStatus.remove(); diff --git a/lms/static/js/learner_dashboard/views/program_alert_list_view.js b/lms/static/js/learner_dashboard/views/program_alert_list_view.js deleted file mode 100644 index 6c42d85444..0000000000 --- a/lms/static/js/learner_dashboard/views/program_alert_list_view.js +++ /dev/null @@ -1,89 +0,0 @@ -import Backbone from 'backbone'; - -import HtmlUtils from 'edx-ui-toolkit/js/utils/html-utils'; -import StringUtils from 'edx-ui-toolkit/js/utils/string-utils'; - -import warningIcon from '../../../images/warning-icon.svg'; -import programAlertTpl from '../../../templates/learner_dashboard/program_alert_list_view.underscore'; - -class ProgramAlertListView extends Backbone.View { - constructor(options) { - const defaults = { - el: '.js-program-details-alerts', - }; - // eslint-disable-next-line prefer-object-spread - super(Object.assign({}, defaults, options)); - } - - initialize({ context }) { - this.tpl = HtmlUtils.template(programAlertTpl); - this.enrollmentAlerts = context.enrollmentAlerts || []; - this.trialEndingAlerts = context.trialEndingAlerts || []; - this.pageType = context.pageType; - this.render(); - } - - render() { - const data = { - alertList: this.getAlertList(), - warningIcon, - }; - HtmlUtils.setHtml(this.$el, this.tpl(data)); - } - - getAlertList() { - const alertList = this.enrollmentAlerts.map( - ({ title: programName, url }) => ({ - url, - // eslint-disable-next-line no-undef - urlText: gettext('View program'), - title: StringUtils.interpolate( - // eslint-disable-next-line no-undef - gettext('Enroll in a {programName}\'s course'), - { programName }, - ), - message: this.pageType === 'programDetails' - ? StringUtils.interpolate( - // eslint-disable-next-line no-undef - gettext('You have an active subscription to the {programName} program but are not enrolled in any courses. Enroll in a remaining course and enjoy verified access.'), - { programName }, - ) - : HtmlUtils.interpolateHtml( - // eslint-disable-next-line no-undef - gettext('According to our records, you are not enrolled in any courses included in your {programName} program subscription. Enroll in a course from the {i_start}Program Details{i_end} page.'), - { - programName, - i_start: HtmlUtils.HTML(''), - i_end: HtmlUtils.HTML(''), - }, - ), - }), - ); - return alertList.concat(this.trialEndingAlerts.map( - ({ title: programName, remainingDays, ...data }) => ({ - title: StringUtils.interpolate( - remainingDays < 1 - // eslint-disable-next-line no-undef - ? gettext('Subscription trial expires in less than 24 hours') - // eslint-disable-next-line no-undef - : ngettext('Subscription trial expires in {remainingDays} day', 'Subscription trial expires in {remainingDays} days', remainingDays), - { remainingDays }, - ), - message: StringUtils.interpolate( - remainingDays < 1 - // eslint-disable-next-line no-undef - ? gettext('Your {programName} trial will expire at {trialEndTime} on {trialEndDate} and the card on file will be charged {subscriptionPrice}.') - // eslint-disable-next-line no-undef - : ngettext('Your {programName} trial will expire in {remainingDays} day at {trialEndTime} on {trialEndDate} and the card on file will be charged {subscriptionPrice}.', 'Your {programName} trial will expire in {remainingDays} days at {trialEndTime} on {trialEndDate} and the card on file will be charged {subscriptionPrice}.', remainingDays), - { - programName, - remainingDays, - ...data, - }, - ), - }), - )); - } -} - -export default ProgramAlertListView; diff --git a/lms/static/js/learner_dashboard/views/program_card_view.js b/lms/static/js/learner_dashboard/views/program_card_view.js index 1a5a053135..f4715e2538 100644 --- a/lms/static/js/learner_dashboard/views/program_card_view.js +++ b/lms/static/js/learner_dashboard/views/program_card_view.js @@ -30,10 +30,6 @@ class ProgramCardView extends Backbone.View { uuid: this.model.get('uuid'), }); } - this.isSubscribed = ( - context.isUserB2CSubscriptionsEnabled && - this.model.get('subscriptionIndex') > -1 - ) ?? false; this.render(); } @@ -45,7 +41,6 @@ class ProgramCardView extends Backbone.View { this.getProgramProgress(), { orgList: orgList.join(' '), - isSubscribed: this.isSubscribed, }, ); diff --git a/lms/static/js/learner_dashboard/views/program_details_sidebar_view.js b/lms/static/js/learner_dashboard/views/program_details_sidebar_view.js index fea4ebd809..fa8ccb629b 100644 --- a/lms/static/js/learner_dashboard/views/program_details_sidebar_view.js +++ b/lms/static/js/learner_dashboard/views/program_details_sidebar_view.js @@ -30,9 +30,7 @@ class ProgramDetailsSidebarView extends Backbone.View { this.industryPathways = options.industryPathways; this.creditPathways = options.creditPathways; this.programModel = options.model; - this.subscriptionModel = options.subscriptionModel; this.programTabViewEnabled = options.programTabViewEnabled; - this.isSubscriptionEligible = options.isSubscriptionEligible; this.urls = options.urls; this.render(); } @@ -42,14 +40,12 @@ class ProgramDetailsSidebarView extends Backbone.View { const data = $.extend( {}, this.model.toJSON(), - this.subscriptionModel.toJSON(), { programCertificate: this.programCertificate ? this.programCertificate.toJSON() : {}, industryPathways: this.industryPathways, creditPathways: this.creditPathways, programTabViewEnabled: this.programTabViewEnabled, - isSubscriptionEligible: this.isSubscriptionEligible, arrowUprightIcon, ...this.urls, }, diff --git a/lms/static/js/learner_dashboard/views/program_details_view.js b/lms/static/js/learner_dashboard/views/program_details_view.js index 220840c182..006d30c59b 100644 --- a/lms/static/js/learner_dashboard/views/program_details_view.js +++ b/lms/static/js/learner_dashboard/views/program_details_view.js @@ -10,10 +10,6 @@ import CourseCardView from './course_card_view'; // eslint-disable-next-line import/no-named-as-default, import/no-named-as-default-member import HeaderView from './program_header_view'; import SidebarView from './program_details_sidebar_view'; -import AlertListView from './program_alert_list_view'; - -// eslint-disable-next-line import/no-named-as-default, import/no-named-as-default-member -import SubscriptionModel from '../models/program_subscription_model'; import launchIcon from '../../../images/launch-icon.svg'; import restartIcon from '../../../images/restart-icon.svg'; @@ -27,7 +23,6 @@ class ProgramDetailsView extends Backbone.View { el: '.js-program-details-wrapper', events: { 'click .complete-program': 'trackPurchase', - 'click .js-subscription-cta': 'trackSubscriptionCTA', }, }; // eslint-disable-next-line prefer-object-spread @@ -46,9 +41,6 @@ class ProgramDetailsView extends Backbone.View { this.certificateCollection = new Backbone.Collection( this.options.certificateData, ); - this.subscriptionModel = new SubscriptionModel({ - context: this.options, - }); this.completedCourseCollection = new CourseCardCollection( this.courseData.get('completed') || [], this.options.userPreferences, @@ -61,11 +53,6 @@ class ProgramDetailsView extends Backbone.View { this.courseData.get('not_started') || [], this.options.userPreferences, ); - this.subscriptionEventParams = { - label: this.options.programData.title, - program_uuid: this.options.programData.uuid, - }; - this.options.isSubscriptionEligible = this.getIsSubscriptionEligible(); this.render(); @@ -76,7 +63,6 @@ class ProgramDetailsView extends Backbone.View { pageName: 'program_dashboard', linkCategory: 'green_upgrade', }); - this.trackSubscriptionEligibleProgramView(); } static getUrl(base, programData) { @@ -107,7 +93,6 @@ class ProgramDetailsView extends Backbone.View { creditPathways: this.options.creditPathways, discussionFragment: this.options.discussionFragment, live_fragment: this.options.live_fragment, - isSubscriptionEligible: this.options.isSubscriptionEligible, launchIcon, restartIcon, }; @@ -115,7 +100,6 @@ class ProgramDetailsView extends Backbone.View { data = $.extend( data, this.programModel.toJSON(), - this.subscriptionModel.toJSON(), ); HtmlUtils.setHtml(this.$el, this.tpl(data)); this.postRender(); @@ -126,20 +110,6 @@ class ProgramDetailsView extends Backbone.View { model: new Backbone.Model(this.options), }); - if (this.options.isSubscriptionEligible) { - const { enrollmentAlerts, trialEndingAlerts } = this.getAlerts(); - - if (enrollmentAlerts.length || trialEndingAlerts.length) { - this.alertListView = new AlertListView({ - context: { - enrollmentAlerts, - trialEndingAlerts, - pageType: 'programDetails', - }, - }); - } - } - if (this.remainingCourseCollection.length > 0) { new CollectionListView({ el: '.js-course-list-remaining', @@ -178,12 +148,10 @@ class ProgramDetailsView extends Backbone.View { el: '.js-program-sidebar', model: this.programModel, courseModel: this.courseData, - subscriptionModel: this.subscriptionModel, certificateCollection: this.certificateCollection, industryPathways: this.options.industryPathways, creditPathways: this.options.creditPathways, programTabViewEnabled: this.options.programTabViewEnabled, - isSubscriptionEligible: this.options.isSubscriptionEligible, urls: this.options.urls, }); let hasIframe = false; @@ -197,59 +165,6 @@ class ProgramDetailsView extends Backbone.View { }).bind(this); } - getIsSubscriptionEligible() { - const courseCollections = [ - this.completedCourseCollection, - this.inProgressCourseCollection, - ]; - const isSomeCoursePurchasable = courseCollections.some((collection) => ( - collection.some((course) => ( - course.get('upgrade_url') - && !(course.get('expired') === true) - )) - )); - const programPurchasedWithoutSubscription = ( - this.subscriptionModel.get('subscriptionState') !== 'active' - && this.subscriptionModel.get('subscriptionState') !== 'inactive' - && !isSomeCoursePurchasable - && this.remainingCourseCollection.length === 0 - ); - - const isSubscriptionActiveSunsetting = ( - this.subscriptionModel.get('subscriptionState') === 'active' - ) - - return ( - this.options.isUserB2CSubscriptionsEnabled - && isSubscriptionActiveSunsetting - && !programPurchasedWithoutSubscription - ); - } - - getAlerts() { - const alerts = { - enrollmentAlerts: [], - trialEndingAlerts: [], - }; - if (this.subscriptionModel.get('subscriptionState') === 'active') { - if (this.courseData.get('all_unenrolled')) { - alerts.enrollmentAlerts.push({ - title: this.programModel.get('title'), - }); - } - if ( - this.subscriptionModel.get('remainingDays') <= 7 - && this.subscriptionModel.get('hasActiveTrial') - ) { - alerts.trialEndingAlerts.push({ - title: this.programModel.get('title'), - ...this.subscriptionModel.toJSON(), - }); - } - } - return alerts; - } - trackPurchase() { const data = this.options.programData; window.analytics.track('edx.bi.user.dashboard.program.purchase', { @@ -258,37 +173,6 @@ class ProgramDetailsView extends Backbone.View { uuid: data.uuid, }); } - - trackSubscriptionCTA() { - const state = this.subscriptionModel.get('subscriptionState'); - - if (state === 'active') { - window.analytics.track( - 'edx.bi.user.subscription.program-detail-page.manage.clicked', - this.subscriptionEventParams, - ); - } else { - const isNewSubscription = state !== 'inactive'; - window.analytics.track( - 'edx.bi.user.subscription.program-detail-page.subscribe.clicked', - { - category: `${this.options.programData.variant} bundle`, - is_new_subscription: isNewSubscription, - is_trial_eligible: isNewSubscription, - ...this.subscriptionEventParams, - }, - ); - } - } - - trackSubscriptionEligibleProgramView() { - if (this.options.isSubscriptionEligible) { - window.analytics.track( - 'edx.bi.user.subscription.program-detail-page.viewed', - this.subscriptionEventParams, - ); - } - } } export default ProgramDetailsView; diff --git a/lms/static/js/learner_dashboard/views/program_header_view.js b/lms/static/js/learner_dashboard/views/program_header_view.js index 2fd8e9fe51..acb3c876ca 100644 --- a/lms/static/js/learner_dashboard/views/program_header_view.js +++ b/lms/static/js/learner_dashboard/views/program_header_view.js @@ -42,22 +42,11 @@ class ProgramHeaderView extends Backbone.View { return logo; } - getIsSubscribed() { - const isSubscriptionEligible = this.model.get('isSubscriptionEligible'); - const subscriptionData = this.model.get('subscriptionData')?.[0]; - - return ( - isSubscriptionEligible && - subscriptionData?.subscription_state === 'active' - ); - } - render() { // eslint-disable-next-line no-undef const data = $.extend(this.model.toJSON(), { breakpoints: this.breakpoints, logo: this.getLogo(), - isSubscribed: this.getIsSubscribed(), }); if (this.model.get('programData')) { diff --git a/lms/static/js/learner_dashboard/views/program_list_header_view.js b/lms/static/js/learner_dashboard/views/program_list_header_view.js index 6520caf086..98e628cefa 100644 --- a/lms/static/js/learner_dashboard/views/program_list_header_view.js +++ b/lms/static/js/learner_dashboard/views/program_list_header_view.js @@ -2,10 +2,6 @@ import Backbone from 'backbone'; import HtmlUtils from 'edx-ui-toolkit/js/utils/html-utils'; -import AlertListView from './program_alert_list_view'; - -import SubscriptionModel from '../models/program_subscription_model'; - import programListHeaderTpl from '../../../templates/learner_dashboard/program_list_header_view.underscore'; class ProgramListHeaderView extends Backbone.View { @@ -19,76 +15,11 @@ class ProgramListHeaderView extends Backbone.View { initialize({ context }) { this.context = context; this.tpl = HtmlUtils.template(programListHeaderTpl); - this.programAndSubscriptionData = context.programsData - .map((programData) => ({ - programData, - subscriptionData: context.subscriptionCollection - ?.findWhere({ - resource_id: programData.uuid, - subscription_state: 'active', - }) - ?.toJSON(), - })) - .filter(({ subscriptionData }) => !!subscriptionData); this.render(); } render() { HtmlUtils.setHtml(this.$el, this.tpl(this.context)); - this.postRender(); - } - - postRender() { - if (this.context.isUserB2CSubscriptionsEnabled) { - const enrollmentAlerts = this.getEnrollmentAlerts(); - const trialEndingAlerts = this.getTrialEndingAlerts(); - - if (enrollmentAlerts.length || trialEndingAlerts.length) { - this.alertListView = new AlertListView({ - el: '.js-program-list-alerts', - context: { - enrollmentAlerts, - trialEndingAlerts, - pageType: 'programList', - }, - }); - } - } - } - - getEnrollmentAlerts() { - return this.programAndSubscriptionData - .map(({ programData, subscriptionData }) => - this.context.progressCollection?.findWhere({ - uuid: programData.uuid, - all_unenrolled: true, - }) ? { - title: programData.title, - url: programData.detail_url, - } : null - ) - .filter(Boolean); - } - - getTrialEndingAlerts() { - return this.programAndSubscriptionData - .map(({ programData, subscriptionData }) => { - const subscriptionModel = new SubscriptionModel({ - context: { - programData, - subscriptionData: [subscriptionData], - userPreferences: this.context?.userPreferences, - }, - }); - return ( - subscriptionModel.get('remainingDays') <= 7 && - subscriptionModel.get('hasActiveTrial') && { - title: programData.title, - ...subscriptionModel.toJSON(), - } - ); - }) - .filter(Boolean); } } diff --git a/lms/static/js/learner_dashboard/views/sidebar_view.js b/lms/static/js/learner_dashboard/views/sidebar_view.js index 3359eac1b4..520efbe29f 100644 --- a/lms/static/js/learner_dashboard/views/sidebar_view.js +++ b/lms/static/js/learner_dashboard/views/sidebar_view.js @@ -10,9 +10,6 @@ class SidebarView extends Backbone.View { constructor(options) { const defaults = { el: '.sidebar', - events: { - 'click .js-subscription-upsell-cta ': 'trackSubscriptionUpsellCTA', - }, }; // eslint-disable-next-line prefer-object-spread super(Object.assign({}, defaults, options)); @@ -33,12 +30,6 @@ class SidebarView extends Backbone.View { context: this.context, }); } - - trackSubscriptionUpsellCTA() { - window.analytics.track( - 'edx.bi.user.subscription.program-dashboard.upsell.clicked', - ); - } } export default SidebarView; diff --git a/lms/static/js/learner_dashboard/views/subscription_upsell_view.js b/lms/static/js/learner_dashboard/views/subscription_upsell_view.js deleted file mode 100644 index 3c085aaf7e..0000000000 --- a/lms/static/js/learner_dashboard/views/subscription_upsell_view.js +++ /dev/null @@ -1,30 +0,0 @@ -import Backbone from 'backbone'; - -import HtmlUtils from 'edx-ui-toolkit/js/utils/html-utils'; - -import subscriptionUpsellTpl from '../../../templates/learner_dashboard/subscription_upsell_view.underscore'; - -class SubscriptionUpsellView extends Backbone.View { - constructor(options) { - const defaults = { - el: '.js-subscription-upsell', - }; - // eslint-disable-next-line prefer-object-spread - super(Object.assign({}, defaults, options)); - } - - initialize(options) { - this.tpl = HtmlUtils.template(subscriptionUpsellTpl); - this.subscriptionUpsellModel = new Backbone.Model( - options.subscriptionUpsellData, - ); - this.render(); - } - - render() { - const data = this.subscriptionUpsellModel.toJSON(); - HtmlUtils.setHtml(this.$el, this.tpl(data)); - } -} - -export default SubscriptionUpsellView; diff --git a/lms/static/js/learner_dashboard/views/upgrade_message_view.js b/lms/static/js/learner_dashboard/views/upgrade_message_view.js index 07d1b9522e..c8ad363286 100644 --- a/lms/static/js/learner_dashboard/views/upgrade_message_view.js +++ b/lms/static/js/learner_dashboard/views/upgrade_message_view.js @@ -3,18 +3,12 @@ import Backbone from 'backbone'; import HtmlUtils from 'edx-ui-toolkit/js/utils/html-utils'; import upgradeMessageTpl from '../../../templates/learner_dashboard/upgrade_message.underscore'; -import upgradeMessageSubscriptionTpl from '../../../templates/learner_dashboard/upgrade_message_subscription.underscore'; import trackECommerceEvents from '../../commerce/track_ecommerce_events'; class UpgradeMessageView extends Backbone.View { initialize(options) { - if (options.isSubscriptionEligible) { - this.messageTpl = HtmlUtils.template(upgradeMessageSubscriptionTpl); - } else { - this.messageTpl = HtmlUtils.template(upgradeMessageTpl); - } + this.messageTpl = HtmlUtils.template(upgradeMessageTpl); this.$el = options.$el; - this.subscriptionModel = options.subscriptionModel; this.render(); const courseUpsellButtons = this.$el.find('.program_dashboard_course_upsell_button'); @@ -30,7 +24,6 @@ class UpgradeMessageView extends Backbone.View { const data = $.extend( {}, this.model.toJSON(), - this.subscriptionModel.toJSON(), ); HtmlUtils.setHtml(this.$el, this.messageTpl(data)); } diff --git a/lms/static/sass/views/_program-details.scss b/lms/static/sass/views/_program-details.scss index 9056f04a13..f5a6eb62b5 100644 --- a/lms/static/sass/views/_program-details.scss +++ b/lms/static/sass/views/_program-details.scss @@ -90,21 +90,6 @@ $btn-color-primary: $primary-dark; } } -.program-details-alerts { - .page-banner { - margin: 0; - padding: 0 0 48px; - gap: 24px; - } -} - -.program-details-tab-alerts { - .page-banner { - margin: 0; - gap: 24px; - } -} - // CSS for April 2017 version of Program Details Page .program-details { .window-wrap { @@ -449,42 +434,6 @@ $btn-color-primary: $primary-dark; } } - .upgrade-subscription { - margin: 16px 0 10px; - row-gap: 16px; - column-gap: 24px; - } - - .subscription-icon-launch { - width: 22.5px; - height: 22.5px; - margin-inline-start: 8px; - } - - .subscription-icon-restart { - width: 22.5px; - height: 22.5px; - margin-inline-end: 8px; - } - - .subscription-icon-arrow-upright { - display: inline-flex; - align-items: center; - width: 15px; - height: 15px; - margin-inline-start: 8px; - } - - .subscription-info-brief { - font-size: 0.9375em; - color: $gray-500; - } - - .subscription-info-upsell { - margin-top: 0.25rem; - font-size: 0.8125em; - } - .program-course-card { width: 100%; padding: 15px 15px 15px 0px; @@ -681,24 +630,6 @@ $btn-color-primary: $primary-dark; .program-sidebar { padding: 40px 40px 40px 0px; - .program-record,.subscription-info { - text-align: left; - padding-bottom: 2em; - } - - .subscription-section { - display: flex; - flex-direction: column; - gap: 16px; - color: #414141; - - .subscription-link { - color: inherit; - text-decoration: none; - border-bottom: 1px solid currentColor; - } - } - .sidebar-section { font-size: 0.9375em; width: auto; diff --git a/lms/static/sass/views/_program-list.scss b/lms/static/sass/views/_program-list.scss index 23f9a78b7c..d05e2eb285 100644 --- a/lms/static/sass/views/_program-list.scss +++ b/lms/static/sass/views/_program-list.scss @@ -39,13 +39,6 @@ .program-cards-container { @include grid-container(); padding-top: 32px; - - .subscription-badge { - position: absolute; - top: 8px; - left: 8px; - z-index: 10; - } } .sidebar { diff --git a/lms/templates/learner_dashboard/program_card.underscore b/lms/templates/learner_dashboard/program_card.underscore index c9364d6ca2..de98c952dd 100644 --- a/lms/templates/learner_dashboard/program_card.underscore +++ b/lms/templates/learner_dashboard/program_card.underscore @@ -61,8 +61,3 @@ -<% if (isSubscribed) { %> -
- <%- gettext('Subscribed') %> -
-<% } %> diff --git a/lms/templates/learner_dashboard/program_details_fragment.html b/lms/templates/learner_dashboard/program_details_fragment.html index 7aff07a6a3..70571ca80f 100644 --- a/lms/templates/learner_dashboard/program_details_fragment.html +++ b/lms/templates/learner_dashboard/program_details_fragment.html @@ -14,7 +14,6 @@ from openedx.core.djangolib.js_utils import ( <%static:webpack entry="ProgramDetailsFactory"> ProgramDetailsFactory({ programData: ${program_data | n, dump_js_escaped_json}, - subscriptionData: ${program_subscription_data | n, dump_js_escaped_json}, courseData: ${course_data | n, dump_js_escaped_json}, certificateData: ${certificate_data | n, dump_js_escaped_json}, urls: ${urls | n, dump_js_escaped_json}, @@ -22,8 +21,6 @@ ProgramDetailsFactory({ industryPathways: ${industry_pathways | n, dump_js_escaped_json}, creditPathways: ${credit_pathways | n, dump_js_escaped_json}, programTabViewEnabled: ${program_tab_view_enabled | n, dump_js_escaped_json}, - isUserB2CSubscriptionsEnabled: ${is_user_b2c_subscriptions_enabled | n, dump_js_escaped_json}, - subscriptionsTrialLength: ${subscriptions_trial_length | n, dump_js_escaped_json}, discussionFragment: ${discussion_fragment, | n, dump_js_escaped_json}, live_fragment: ${live_fragment, | n, dump_js_escaped_json} }); diff --git a/lms/templates/learner_dashboard/program_details_sidebar.underscore b/lms/templates/learner_dashboard/program_details_sidebar.underscore index cab7aad04b..0e05ae9b9a 100644 --- a/lms/templates/learner_dashboard/program_details_sidebar.underscore +++ b/lms/templates/learner_dashboard/program_details_sidebar.underscore @@ -8,50 +8,6 @@ <% } %> -<% if (isSubscriptionEligible) { %> - -<% } %>