From 7851161cbf80d45715961ef9ce6c55131fca0062 Mon Sep 17 00:00:00 2001 From: Hamzah Ullah Date: Thu, 19 Dec 2024 17:33:33 +0000 Subject: [PATCH] fix: set enrollment url course id to advertised course run key --- .../apps/catalog/algolia_utils.py | 22 ++-------- .../apps/catalog/content_metadata_utils.py | 19 ++++++++- enterprise_catalog/apps/catalog/models.py | 8 +++- .../apps/catalog/tests/factories.py | 2 +- .../apps/catalog/tests/test_algolia_utils.py | 4 +- .../apps/catalog/tests/test_models.py | 40 +++++++++++++++++++ .../apps/catalog/tests/test_serializers.py | 4 +- enterprise_catalog/apps/catalog/utils.py | 18 --------- 8 files changed, 76 insertions(+), 41 deletions(-) diff --git a/enterprise_catalog/apps/catalog/algolia_utils.py b/enterprise_catalog/apps/catalog/algolia_utils.py index 80e9cc23..cb51205e 100644 --- a/enterprise_catalog/apps/catalog/algolia_utils.py +++ b/enterprise_catalog/apps/catalog/algolia_utils.py @@ -31,6 +31,7 @@ VIDEO, ) from enterprise_catalog.apps.catalog.content_metadata_utils import ( + get_advertised_course_run, get_course_first_paid_enrollable_seat_price, get_course_run_by_uuid, is_course_run_active, @@ -1168,23 +1169,6 @@ def _get_course_run(course, course_run): return course_run -def get_advertised_course_run(course): - """ - Get part of the advertised course_run as per advertised_course_run_uuid - - Argument: - course (dict) - - Returns: - dict: containing key, pacing_type, start, end, and upgrade deadline - for the course_run, or None - """ - full_course_run = get_course_run_by_uuid(course, course.get('advertised_course_run_uuid')) - if full_course_run is None: - return None - return _get_course_run(course, full_course_run) - - def get_course_runs(course): """ Extract and transform a list of course runs into what we'll index. @@ -1514,6 +1498,8 @@ def _algolia_object_from_product(product, algolia_fields): """ searchable_product = copy.deepcopy(product) if searchable_product.get('content_type') == COURSE: + advertised_course_run = get_advertised_course_run(searchable_product) + transformed_advertised_course_run = _get_course_run(searchable_product, advertised_course_run) searchable_product.update({ 'language': get_course_language(searchable_product), 'availability': get_course_availability(searchable_product), @@ -1522,7 +1508,7 @@ def _algolia_object_from_product(product, algolia_fields): 'program_titles': get_course_program_titles(searchable_product), 'subjects': get_course_subjects(searchable_product), 'card_image_url': get_course_card_image_url(searchable_product), - 'advertised_course_run': get_advertised_course_run(searchable_product), + 'advertised_course_run': transformed_advertised_course_run, 'course_runs': get_course_runs(searchable_product), 'upcoming_course_runs': get_upcoming_course_runs(searchable_product), 'skill_names': get_course_skill_names(searchable_product), diff --git a/enterprise_catalog/apps/catalog/content_metadata_utils.py b/enterprise_catalog/apps/catalog/content_metadata_utils.py index da894034..60739e27 100644 --- a/enterprise_catalog/apps/catalog/content_metadata_utils.py +++ b/enterprise_catalog/apps/catalog/content_metadata_utils.py @@ -89,7 +89,7 @@ def get_course_first_paid_enrollable_seat_price(course): # Use advertised course run. # If that fails use one of the other active course runs. # (The latter is what Discovery does) - advertised_course_run = get_course_run_by_uuid(course, course.get('advertised_course_run_uuid')) + advertised_course_run = get_advertised_course_run(course) if advertised_course_run and advertised_course_run.get('first_enrollable_paid_seat_price'): return advertised_course_run.get('first_enrollable_paid_seat_price') @@ -102,3 +102,20 @@ def get_course_first_paid_enrollable_seat_price(course): if 'first_enrollable_paid_seat_price' in course_run: return course_run['first_enrollable_paid_seat_price'] return None + + +def get_advertised_course_run(course): + """ + Get part of the advertised course_run as per advertised_course_run_uuid + + Argument: + course (dict) + + Returns: + dict: containing key, pacing_type, start, end, and upgrade deadline + for the course_run, or None + """ + full_course_run = get_course_run_by_uuid(course, course.get('advertised_course_run_uuid')) + if full_course_run is None: + return None + return full_course_run diff --git a/enterprise_catalog/apps/catalog/models.py b/enterprise_catalog/apps/catalog/models.py index aaaf7999..b397150c 100644 --- a/enterprise_catalog/apps/catalog/models.py +++ b/enterprise_catalog/apps/catalog/models.py @@ -45,6 +45,7 @@ json_serialized_course_modes, ) from enterprise_catalog.apps.catalog.content_metadata_utils import ( + get_advertised_course_run, get_course_first_paid_enrollable_seat_price, ) from enterprise_catalog.apps.catalog.utils import ( @@ -555,10 +556,15 @@ def get_content_enrollment_url(self, content_metadata): else: # Catalog param only needed for legacy (non-learner-portal) enrollment URLs params['catalog'] = self.uuid + + course_run_key = content_key + if not parent_content_key: + if advertised_course_run := get_advertised_course_run(content_metadata.json_metadata): + course_run_key = advertised_course_run['key'] url = '{}/enterprise/{}/course/{}/enroll/'.format( settings.LMS_BASE_URL, self.enterprise_uuid, - content_key, + course_run_key, ) return update_query_parameters(url, params) diff --git a/enterprise_catalog/apps/catalog/tests/factories.py b/enterprise_catalog/apps/catalog/tests/factories.py index 45fab4b4..93ef6394 100644 --- a/enterprise_catalog/apps/catalog/tests/factories.py +++ b/enterprise_catalog/apps/catalog/tests/factories.py @@ -99,7 +99,7 @@ def _json_metadata(self): 'logo_image_url': fake.image_url() + '.jpg', }] course_runs = [{ - 'key': 'course-v1:edX+DemoX', + 'key': 'course-v1:edX+DemoX+2T2024', 'uuid': str(FAKE_ADVERTISED_COURSE_RUN_UUID), 'content_language': 'en-us', 'status': 'published', diff --git a/enterprise_catalog/apps/catalog/tests/test_algolia_utils.py b/enterprise_catalog/apps/catalog/tests/test_algolia_utils.py index 5309f5c5..9594abac 100644 --- a/enterprise_catalog/apps/catalog/tests/test_algolia_utils.py +++ b/enterprise_catalog/apps/catalog/tests/test_algolia_utils.py @@ -6,6 +6,7 @@ from django.test import TestCase from enterprise_catalog.apps.catalog import algolia_utils as utils +from enterprise_catalog.apps.catalog.algolia_utils import _get_course_run from enterprise_catalog.apps.catalog.constants import ( ALGOLIA_DEFAULT_TIMESTAMP, COURSE, @@ -508,7 +509,8 @@ def test_get_advertised_course_run(self, searchable_course, expected_course_run) Assert get_advertised_course_runs fetches just enough info about advertised course run """ advertised_course_run = utils.get_advertised_course_run(searchable_course) - assert advertised_course_run == expected_course_run + transformed_advertised_course_run = _get_course_run(searchable_course, advertised_course_run) + assert transformed_advertised_course_run == expected_course_run @ddt.data( ( diff --git a/enterprise_catalog/apps/catalog/tests/test_models.py b/enterprise_catalog/apps/catalog/tests/test_models.py index 03b7367f..47f97e32 100644 --- a/enterprise_catalog/apps/catalog/tests/test_models.py +++ b/enterprise_catalog/apps/catalog/tests/test_models.py @@ -623,6 +623,46 @@ def test_get_content_enrollment_url( else: assert settings.LMS_BASE_URL in content_enrollment_url + @ddt.data( + { + 'content_key': 'course-v1:edX+DemoX+2T2024', + 'parent_content_key': 'edX+DemoX', + }, + { + 'content_key': 'edX+DemoX', + 'parent_content_key': None + }, + ) + @ddt.unpack + def test_get_content_enrollment_url_disabled_learner_portal( + self, + content_key, + parent_content_key, + ): + enterprise_uuid = uuid4() + enterprise_slug = 'sluggy' + + enterprise_catalog = factories.EnterpriseCatalogFactory(enterprise_uuid=enterprise_uuid) + content_metadata = factories.ContentMetadataFactory( + content_key=content_key, + parent_content_key=parent_content_key, + content_type=COURSE, + ) + + enterprise_catalog.catalog_query.contentmetadata_set.add(*[content_metadata]) + + mock_enterprise_customer_return_value = { + 'slug': enterprise_slug, + 'enable_learner_portal': False, + } + + with self._mock_enterprise_customer_cache( + mock_enterprise_customer_return_value, + ): + content_enrollment_url = enterprise_catalog.get_content_enrollment_url(content_metadata) + + assert "/course/course-v1:edX+DemoX+2T2024/enroll/" in content_enrollment_url + @mock.patch('enterprise_catalog.apps.api_client.enterprise_cache.EnterpriseApiClient') @ddt.data( { diff --git a/enterprise_catalog/apps/catalog/tests/test_serializers.py b/enterprise_catalog/apps/catalog/tests/test_serializers.py index 78ada547..82430e96 100644 --- a/enterprise_catalog/apps/catalog/tests/test_serializers.py +++ b/enterprise_catalog/apps/catalog/tests/test_serializers.py @@ -8,11 +8,13 @@ COURSE, EXEC_ED_2U_COURSE_TYPE, ) +from enterprise_catalog.apps.catalog.content_metadata_utils import ( + get_course_run_by_uuid, +) from enterprise_catalog.apps.catalog.serializers import ( NormalizedContentMetadataSerializer, ) from enterprise_catalog.apps.catalog.tests import factories -from enterprise_catalog.apps.catalog.utils import get_course_run_by_uuid @ddt.ddt diff --git a/enterprise_catalog/apps/catalog/utils.py b/enterprise_catalog/apps/catalog/utils.py index 7a046424..ada81ea9 100644 --- a/enterprise_catalog/apps/catalog/utils.py +++ b/enterprise_catalog/apps/catalog/utils.py @@ -158,21 +158,3 @@ def to_timestamp(datetime_str): except (ValueError, TypeError) as exc: LOGGER.error(f"[to_timestamp][{exc}] Could not parse date string: {datetime_str}") return None - - -def get_course_run_by_uuid(course, course_run_uuid): - """ - Find a course_run based on uuid - - Arguments: - course (dict): course dict - course_run_uuid (str): uuid to lookup - - Returns: - dict: a course_run or None - """ - try: - course_run = [run for run in course.get('course_runs', []) if run.get('uuid') == course_run_uuid][0] - except IndexError: - return None - return course_run