Skip to content

Commit

Permalink
feat: add course key param to track selection url (#33716)
Browse files Browse the repository at this point in the history
  • Loading branch information
aht007 authored Nov 24, 2023
1 parent f880855 commit a57dd73
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 4 deletions.
44 changes: 44 additions & 0 deletions common/djangoapps/course_modes/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,50 @@ def test_no_id_redirect_otto(self):
self.assertRedirects(response, '/test_basket/add/?sku=TEST', fetch_redirect_response=False)
ecomm_test_utils.update_commerce_config(enabled=False)

def test_verified_mode_response_contains_course_run_key(self):
# Create only the verified mode and enroll the user
CourseModeFactory.create(
mode_slug='verified',
course_id=self.course_that_started.id,
min_price=149,
sku="dummy"
)
CourseEnrollmentFactory(
is_active=True,
course_id=self.course_that_started.id,
user=self.user
)

# Value Prop TODO (REV-2378): remove waffle flag from tests once the new Track Selection template is rolled out.
with override_waffle_flag(VALUE_PROP_TRACK_SELECTION_FLAG, active=True):
with patch(GATING_METHOD_NAME, return_value=True):
with patch(CDL_METHOD_NAME, return_value=True):
with patch("common.djangoapps.course_modes.views.EcommerceService.is_enabled", return_value=True):
url = reverse('course_modes_choose', args=[str(self.course_that_started.id)])
response = self.client.get(url)
self.assertContains(response, "&course_run_key=")
self.assertContains(response, self.course_that_started.id)

def test_response_without_verified_sku_does_not_contain_course_run_key(self):
CourseModeFactory.create(
mode_slug='verified',
course_id=self.course_that_started.id,
)
CourseEnrollmentFactory(
is_active=True,
course_id=self.course_that_started.id,
user=self.user
)

# Value Prop TODO (REV-2378): remove waffle flag from tests once the new Track Selection template is rolled out.
with override_waffle_flag(VALUE_PROP_TRACK_SELECTION_FLAG, active=True):
with patch(GATING_METHOD_NAME, return_value=True):
with patch(CDL_METHOD_NAME, return_value=True):
with patch("common.djangoapps.course_modes.views.EcommerceService.is_enabled", return_value=True):
url = reverse('course_modes_choose', args=[str(self.course_that_started.id)])
response = self.client.get(url)
self.assertNotContains(response, "&course_run_key=")

@httpretty.activate
@ddt.data(
'',
Expand Down
3 changes: 2 additions & 1 deletion common/djangoapps/course_modes/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def get(self, request, course_id, error=None): # lint-amnesty, pylint: disable=
"content_gating_enabled": gated_content,
"course_duration_limit_enabled": CourseDurationLimitConfig.enabled_for_enrollment(request.user, course),
"search_courses_url": urljoin(settings.MKTG_URLS.get('ROOT'), '/search?tab=course'),
"course_run_key": course_id,
}
context.update(
get_experiment_user_metadata_context(
Expand Down Expand Up @@ -236,7 +237,7 @@ def get(self, request, course_id, error=None): # lint-amnesty, pylint: disable=

if verified_mode.sku:
context["use_ecommerce_payment_flow"] = ecommerce_service.is_enabled(request.user)
context["ecommerce_payment_page"] = ecommerce_service.payment_page_url()
context["ecommerce_payment_page"] = ecommerce_service.get_add_to_basket_url()
context["sku"] = verified_mode.sku
context["bulk_sku"] = verified_mode.bulk_sku

Expand Down
26 changes: 25 additions & 1 deletion lms/djangoapps/commerce/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.test import TestCase
from django.test.client import RequestFactory
from django.test.utils import override_settings
from edx_toggles.toggles.testutils import override_waffle_flag
from opaque_keys.edx.locator import CourseLocator
from waffle.testutils import override_switch

Expand All @@ -20,9 +21,11 @@
from common.djangoapps.student.tests.factories import TEST_PASSWORD, UserFactory
from lms.djangoapps.commerce.models import CommerceConfiguration
from lms.djangoapps.commerce.utils import EcommerceService, refund_entitlement, refund_seat
from lms.djangoapps.commerce.waffle import ENABLE_TRANSITION_TO_COORDINATOR_CHECKOUT
from openedx.core.djangolib.testing.utils import skip_unless_lms
from openedx.core.lib.log_utils import audit_log
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.modulestore.tests.django_utils import \
ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order

# Entitlements is not in CMS' INSTALLED_APPS so these imports will error during test collection
Expand Down Expand Up @@ -183,6 +186,27 @@ def test_get_checkout_page_url_with_enterprise_catalog_uuid(self, skus, enterpri

assert url == expected_url

@override_settings(COMMERCE_COORDINATOR_URL_ROOT='http://coordinator_url')
@override_settings(ECOMMERCE_PUBLIC_URL_ROOT='http://ecommerce_url')
@ddt.data(
{'coordinator_flag_active': True},
{'coordinator_flag_active': False}
)
@ddt.unpack
def test_get_add_to_basket_url(self, coordinator_flag_active):
with override_waffle_flag(ENABLE_TRANSITION_TO_COORDINATOR_CHECKOUT, active=coordinator_flag_active):

ecommerce_service = EcommerceService()
result = ecommerce_service.get_add_to_basket_url()

if coordinator_flag_active:
expected_url = 'http://coordinator_url/lms/redirect/'
else:
expected_url = 'http://ecommerce_url/test_basket/add/'

self.assertIsNotNone(result)
self.assertEqual(result, expected_url)


@ddt.ddt
@skip_unless_lms
Expand Down
12 changes: 12 additions & 0 deletions lms/djangoapps/commerce/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from opaque_keys.edx.keys import CourseKey

from common.djangoapps.course_modes.models import CourseMode
from lms.djangoapps.commerce.waffle import should_redirect_to_commerce_coordinator_checkout
from openedx.core.djangoapps.commerce.utils import (
get_ecommerce_api_base_url,
get_ecommerce_api_client,
Expand Down Expand Up @@ -43,6 +44,7 @@ def is_account_activation_requirement_disabled():

class EcommerceService:
""" Helper class for ecommerce service integration. """

def __init__(self):
self.config = CommerceConfiguration.current()

Expand Down Expand Up @@ -103,6 +105,16 @@ def payment_page_url(self):
"""
return self.get_absolute_ecommerce_url(self.config.basket_checkout_page)

def get_add_to_basket_url(self):
""" Return the URL for the payment page based on the waffle switch.
Example:
http://localhost/enabled_service_api_path
"""
if should_redirect_to_commerce_coordinator_checkout():
return urljoin(settings.COMMERCE_COORDINATOR_URL_ROOT, settings.COORDINATOR_CHECKOUT_REDIRECT_PATH)
return self.payment_page_url()

def get_checkout_page_url(self, *skus, **kwargs):
""" Construct the URL to the ecommerce checkout page and include products.
Expand Down
29 changes: 29 additions & 0 deletions lms/djangoapps/commerce/waffle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Configuration for features of Commerce App
"""
from edx_toggles.toggles import WaffleFlag

# Namespace for Commerce waffle flags.
WAFFLE_FLAG_NAMESPACE = "commerce"

# .. toggle_name: commerce.transition_to_coordinator.checkout
# .. toggle_implementation: WaffleFlag
# .. toggle_default: False
# .. toggle_description: Allows to redirect checkout to Commerce Coordinator API
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2023-11-22
# .. toggle_target_removal_date: TBA
# .. toggle_tickets: SONIC-99
# .. toggle_status: supported
ENABLE_TRANSITION_TO_COORDINATOR_CHECKOUT = WaffleFlag(
f"{WAFFLE_FLAG_NAMESPACE}.transition_to_coordinator.checkout",
__name__,
)


def should_redirect_to_commerce_coordinator_checkout():
"""
Redirect learners to Commerce coordinator checkout.
"""
return ENABLE_TRANSITION_TO_COORDINATOR_CHECKOUT.is_enabled()
4 changes: 4 additions & 0 deletions lms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4225,6 +4225,10 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring
ECOMMERCE_SERVICE_WORKER_USERNAME = 'ecommerce_worker'
ECOMMERCE_API_SIGNING_KEY = 'SET-ME-PLEASE'

# E-Commerce Commerce Coordinator Configuration
COMMERCE_COORDINATOR_URL_ROOT = 'http://localhost:8000'
COORDINATOR_CHECKOUT_REDIRECT_PATH = '/lms/redirect/'

# Exam Service
EXAMS_SERVICE_URL = 'http://localhost:18740/api/v1'

Expand Down
3 changes: 2 additions & 1 deletion lms/templates/course_modes/choose.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
$('button[name=verified_mode]').click(function(e){
e.preventDefault();
window.location.href = '${ecommerce_payment_page | n, js_escaped_string}?sku=' +
encodeURIComponent('${sku | n, js_escaped_string}');
encodeURIComponent('${sku | n, js_escaped_string}') +
'&course_run_key=' + encodeURIComponent('${course_run_key | n, js_escaped_string}');
});
% endif
});
Expand Down
3 changes: 2 additions & 1 deletion lms/templates/course_modes/track_selection.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
$('button[name=verified_mode]').click(function(e){
e.preventDefault();
window.location.href = '${ecommerce_payment_page | n, js_escaped_string}?sku=' +
encodeURIComponent('${sku | n, js_escaped_string}');
encodeURIComponent('${sku | n, js_escaped_string}') +
'&course_run_key=' + encodeURIComponent('${course_run_key | n, js_escaped_string}');
});
});
% endif
Expand Down

0 comments on commit a57dd73

Please sign in to comment.