Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add content_price field to normalized_metadata #703

Merged
merged 2 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading