Skip to content

Commit

Permalink
feat: add content_price field to normalized_metadata (#703)
Browse files Browse the repository at this point in the history
* feat: add content_price field to normalized_metadata

* fix: refactored
  • Loading branch information
katrinan029 authored Oct 26, 2023
1 parent e4c43c8 commit 201b3fe
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 12 deletions.
16 changes: 10 additions & 6 deletions enterprise_catalog/apps/api/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,31 +290,35 @@ def _normalize_course_metadata(course_metadata_record):
Add normalized metadata keys with values calculated by normalizing existing keys. This will be helpful for
downstream consumers which no longer will need to do their own independent normalization.
At the time of writing, output normalized metadata keys incldue:
At the time of writing, output normalized metadata keys include:
* normalized_metadata.start_date: When the course starts
* normalized_metadata.end_date: When the course ends
* normalized_metadata.enroll_by_date: The deadline for enrollment
* normalized_metadata.content_price: The price of a course
Note that course-type-specific definitions of each of these keys may be more nuanced.
"""
json_meta = course_metadata_record.json_metadata
normalized_metadata = {}

# For each content type, find the values that correspond to the desired output key.
if course_metadata_record.is_exec_ed_2u_course:
# First case covers Exec Ed courses.
additional_metdata = json_meta.get('additional_metadata', {})
normalized_metadata['start_date'] = additional_metdata.get('start_date')
normalized_metadata['end_date'] = additional_metdata.get('end_date')
normalized_metadata['enroll_by_date'] = additional_metdata.get('registration_deadline')
additional_metadata = json_meta.get('additional_metadata', {})
normalized_metadata['start_date'] = additional_metadata.get('start_date')
normalized_metadata['end_date'] = additional_metadata.get('end_date')
normalized_metadata['enroll_by_date'] = additional_metadata.get('registration_deadline')
for entitlement in json_meta.get('entitlements', []):
if entitlement.get('mode') == CourseMode.PAID_EXECUTIVE_EDUCATION:
normalized_metadata['content_price'] = entitlement.get('price')
else:
# Else case covers OCM courses.
advertised_course_run_uuid = json_meta.get('advertised_course_run_uuid')
advertised_course_run = _get_course_run_by_uuid(json_meta, advertised_course_run_uuid)
if advertised_course_run is not None:
normalized_metadata['start_date'] = advertised_course_run.get('start')
normalized_metadata['end_date'] = advertised_course_run.get('end')
normalized_metadata['content_price'] = advertised_course_run.get('first_enrollable_paid_seat_price')
all_seats = advertised_course_run.get('seats', [])
seat = _find_best_mode_seat(all_seats)
if seat:
Expand Down
24 changes: 18 additions & 6 deletions enterprise_catalog/apps/api/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class TestTaskResultFunctions(TestCase):
"""
Tests for functions in tasks.py that rely upon `django-celery_results.models.TaskResult`.
"""

def setUp(self):
"""
Delete all TaskResult objects, make a new single result object.
Expand Down Expand Up @@ -421,6 +422,7 @@ def test_update_full_metadata(self, mock_oauth_client, mock_partition_course_key
# The task should copy these dates into net-new top level fields.
'start': '2023-03-01T00:00:00Z',
'end': '2023-03-01T00:00:00Z',
'first_enrollable_paid_seat_price': 90,
'seats': [
{
'type': CourseMode.VERIFIED,
Expand Down Expand Up @@ -480,6 +482,7 @@ def test_update_full_metadata(self, mock_oauth_client, mock_partition_course_key
assert metadata_3.json_metadata['normalized_metadata']['start_date'] == '2023-03-01T00:00:00Z'
assert metadata_3.json_metadata['normalized_metadata']['end_date'] == '2023-03-01T00:00:00Z'
assert metadata_3.json_metadata['normalized_metadata']['enroll_by_date'] == '2023-02-01T00:00:00Z'
assert metadata_3.json_metadata['normalized_metadata']['content_price'] == 90

# make sure course associated program metadata has been created and linked correctly
assert ContentMetadata.objects.filter(content_key=program_key).exists()
Expand Down Expand Up @@ -565,6 +568,12 @@ def test_update_full_metadata_exec_ed(self, mock_oauth_client, mock_partition_co
'end_date': '2023-04-09T23:59:59Z',
'registration_deadline': '2023-02-01T00:00:00Z',
},
'entitlements': [
{
'price': 2900,
'mode': 'paid-executive-education',
},
],
'advertised_course_run_uuid': course_run_uuid,

# Intentionally exclude net-new fields that we will assert are added by the
Expand All @@ -574,6 +583,7 @@ def test_update_full_metadata_exec_ed(self, mock_oauth_client, mock_partition_co
# 'start_date': '2023-03-01T00:00:00Z',
# 'end_date': '2023-04-09T23:59:59Z'
# 'enroll_by_date': '2023-02-01T00:00:00Z',
# 'content_price': 2900,
# }
}

Expand Down Expand Up @@ -616,6 +626,7 @@ def test_update_full_metadata_exec_ed(self, mock_oauth_client, mock_partition_co
# 'start_date': '2023-03-01T00:00:00Z',
# 'end_date': '2023-04-09T23:59:59Z'
# 'enroll_by_date': '2023-02-01T00:00:00Z',
# 'content_price': 2900,
# }
}
)
Expand All @@ -632,6 +643,7 @@ def test_update_full_metadata_exec_ed(self, mock_oauth_client, mock_partition_co
assert course_cm.json_metadata['normalized_metadata']['start_date'] == '2023-03-01T00:00:00Z'
assert course_cm.json_metadata['normalized_metadata']['end_date'] == '2023-04-09T23:59:59Z'
assert course_cm.json_metadata['normalized_metadata']['enroll_by_date'] == '2023-02-01T00:00:00Z'
assert course_cm.json_metadata['normalized_metadata']['content_price'] == 2900

# Make sure the start/end dates are copied from the additional_metadata into the course run dict of the course.
# This checks that the dummy 2022 dates are overwritten.
Expand Down Expand Up @@ -1624,7 +1636,7 @@ def mock_replace_all_objects(products_iterable):
mock_search_client().replace_all_objects.side_effect = mock_replace_all_objects

with mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_UUID_BATCH_SIZE', 1), \
mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_FIELDS', self.ALGOLIA_FIELDS):
mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_FIELDS', self.ALGOLIA_FIELDS):
with self.assertLogs(level='INFO') as info_logs:
tasks.index_enterprise_catalog_in_algolia_task() # pylint: disable=no-value-for-parameter

Expand Down Expand Up @@ -1689,8 +1701,8 @@ def mock_replace_all_objects(products_iterable):
mock_search_client().replace_all_objects.side_effect = mock_replace_all_objects

with mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_UUID_BATCH_SIZE', 1), \
mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_FIELDS', self.ALGOLIA_FIELDS), \
mock.patch('enterprise_catalog.apps.api.tasks.EXPLORE_CATALOG_TITLES', explore_titles):
mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_FIELDS', self.ALGOLIA_FIELDS), \
mock.patch('enterprise_catalog.apps.api.tasks.EXPLORE_CATALOG_TITLES', explore_titles):
with self.assertLogs(level='INFO') as info_logs:
tasks.index_enterprise_catalog_in_algolia_task() # pylint: disable=no-value-for-parameter

Expand Down Expand Up @@ -1763,7 +1775,7 @@ def mock_replace_all_objects(products_iterable):
mock_search_client().replace_all_objects.side_effect = mock_replace_all_objects

with mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_FIELDS', self.ALGOLIA_FIELDS), \
mock.patch('enterprise_catalog.apps.api.tasks.REINDEX_TASK_BATCH_SIZE', 1):
mock.patch('enterprise_catalog.apps.api.tasks.REINDEX_TASK_BATCH_SIZE', 1):
with self.assertLogs(level='INFO') as info_logs:
tasks.index_enterprise_catalog_in_algolia_task() # pylint: disable=no-value-for-parameter

Expand All @@ -1781,8 +1793,8 @@ def test_index_algolia_dry_run(self, mock_search_client):
Make sure the dry_run argument functions correctly and does not call replace_all_objects().
"""
with mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_UUID_BATCH_SIZE', 1), \
mock.patch('enterprise_catalog.apps.api.tasks.REINDEX_TASK_BATCH_SIZE', 10), \
mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_FIELDS', self.ALGOLIA_FIELDS):
mock.patch('enterprise_catalog.apps.api.tasks.REINDEX_TASK_BATCH_SIZE', 10), \
mock.patch('enterprise_catalog.apps.api.tasks.ALGOLIA_FIELDS', self.ALGOLIA_FIELDS):
with self.assertLogs(level='INFO') as info_logs:
# For some reason in order to call a celery task in-memory you must pass kwargs as args.
force = False
Expand Down

0 comments on commit 201b3fe

Please sign in to comment.