diff --git a/enterprise_catalog/apps/catalog/serializers.py b/enterprise_catalog/apps/catalog/serializers.py index 5a9a468c..13904c08 100644 --- a/enterprise_catalog/apps/catalog/serializers.py +++ b/enterprise_catalog/apps/catalog/serializers.py @@ -145,10 +145,14 @@ def get_enroll_by_date(self, obj) -> str: # pylint: disable=unused-argument @extend_schema_field(serializers.FloatField) def get_content_price(self, obj) -> float: # pylint: disable=unused-argument - if self.is_exec_ed_2u_course is True: - for entitlement in self.course_metadata.get('entitlements', []): - if entitlement.get('mode') == CourseMode.PAID_EXECUTIVE_EDUCATION: - return entitlement.get('price') or DEFAULT_NORMALIZED_PRICE if not self.course_run_metadata: return None - return self.course_run_metadata.get('first_enrollable_paid_seat_price') or DEFAULT_NORMALIZED_PRICE + if self.course_run_metadata.get('fixed_price_usd'): + return float(self.course_run_metadata.get('fixed_price_usd')) + if self.is_exec_ed_2u_course is True: + for entitlement in self.course_metadata.get('entitlements', []): + if entitlement.get('price') and entitlement.get('mode') == CourseMode.PAID_EXECUTIVE_EDUCATION: + return float(entitlement.get('price')) + if self.course_run_metadata.get('first_enrollable_paid_seat_price'): + return float(self.course_run_metadata.get('first_enrollable_paid_seat_price')) + return DEFAULT_NORMALIZED_PRICE diff --git a/enterprise_catalog/apps/catalog/tests/factories.py b/enterprise_catalog/apps/catalog/tests/factories.py index edc35d63..d972bdd9 100644 --- a/enterprise_catalog/apps/catalog/tests/factories.py +++ b/enterprise_catalog/apps/catalog/tests/factories.py @@ -127,6 +127,8 @@ def json_metadata(self): ], 'start': '2024-02-12T11:00:00Z', 'end': '2026-02-05T11:00:00Z', + 'fixed_price_price_usd': None, + 'first_enrollable_paid_seat_price': 50, }] json_metadata.update({ 'content_type': COURSE, @@ -136,6 +138,7 @@ def json_metadata(self): 'advertised_course_run_uuid': str(FAKE_ADVERTISED_COURSE_RUN_UUID), 'course_runs': course_runs, 'course': self.content_key, + 'entitlements': [], }) elif self.content_type == COURSE_RUN: json_metadata.update({ diff --git a/enterprise_catalog/apps/catalog/tests/test_serializers.py b/enterprise_catalog/apps/catalog/tests/test_serializers.py index 930ceb28..78ada547 100644 --- a/enterprise_catalog/apps/catalog/tests/test_serializers.py +++ b/enterprise_catalog/apps/catalog/tests/test_serializers.py @@ -12,6 +12,7 @@ NormalizedContentMetadataSerializer, ) from enterprise_catalog.apps.catalog.tests import factories +from enterprise_catalog.apps.catalog.utils import get_course_run_by_uuid @ddt.ddt @@ -29,6 +30,7 @@ def test_enroll_by_date_no_advertised_run(self): normalized_metadata_input = { 'course_metadata': course_content.json_metadata, } + serialized_data = NormalizedContentMetadataSerializer(normalized_metadata_input).data self.assertIsNone(serialized_data['enroll_by_date']) @@ -56,6 +58,7 @@ def test_enroll_by_date_is_exec_ed_course_with_enrollment_end(self, has_course_r } if has_course_run: normalized_metadata_input['course_run_metadata'] = course_content.json_metadata['course_runs'][0] + serialized_data = NormalizedContentMetadataSerializer(normalized_metadata_input).data self.assertEqual(serialized_data['enroll_by_date'], '2024-01-01T00:00:00Z') @@ -118,6 +121,7 @@ def test_enroll_by_date_verified_course_with_seat(self, has_override, has_course } if has_course_run: normalized_metadata_input['course_run_metadata'] = course_content.json_metadata['course_runs'][0] + serialized_data = NormalizedContentMetadataSerializer(normalized_metadata_input).data if has_override: @@ -143,6 +147,93 @@ def test_enroll_by_date_verified_course_no_seat(self, has_course_run): } if has_course_run: normalized_metadata_input['course_run_metadata'] = course_content.json_metadata['course_runs'][0] + serialized_data = NormalizedContentMetadataSerializer(normalized_metadata_input).data self.assertEqual(serialized_data['enroll_by_date'], actual_deadline) + + @ddt.data( + # First enrollable paid seat price + { + 'first_enrollable_paid_seat_price': 50, + 'fixed_price_usd': None, + 'entitlements': [], + 'course_type': 'verified-audit', + 'expected_content_price': 50.0, + }, + # First enrollable paid seat default normalized price + { + 'first_enrollable_paid_seat_price': None, + 'fixed_price_usd': None, + 'entitlements': [], + 'course_type': 'verified-audit', + 'expected_content_price': 0.0, + }, + # Fixed price usd + { + 'first_enrollable_paid_seat_price': 50, + 'fixed_price_usd': "100.00", + 'entitlements': [], + 'course_type': 'verified-audit', + 'expected_content_price': 100.0, + }, + # entitlements + { + 'first_enrollable_paid_seat_price': None, + 'fixed_price_usd': None, + 'entitlements': [ + { + "mode": "paid-executive-education", + "price": "200.00", + "currency": "USD", + "sku": "1234", + "expires": None + } + ], + 'course_type': 'executive-education-2u', + 'expected_content_price': 200.0, + }, + # entitlements default normalized price + { + 'first_enrollable_paid_seat_price': None, + 'fixed_price_usd': None, + 'entitlements': [ + { + "mode": "paid-executive-education", + "price": None, + "currency": "USD", + "sku": "1234", + "expires": None + } + ], + 'course_type': 'executive-education-2u', + 'expected_content_price': 0, + } + ) + @ddt.unpack + def test_content_price(self, + first_enrollable_paid_seat_price, + fixed_price_usd, + entitlements, + course_type, + expected_content_price, + ): + course_content = factories.ContentMetadataFactory( + content_type=COURSE, + ) + course_content.json_metadata['entitlements'] = entitlements + course_content.json_metadata['course_type'] = course_type + + advertised_course_run_uuid = course_content.json_metadata['advertised_course_run_uuid'] + advertised_course_run = get_course_run_by_uuid(course_content.json_metadata, advertised_course_run_uuid) + advertised_course_run['fixed_price_usd'] = fixed_price_usd + advertised_course_run['first_enrollable_paid_seat_price'] = first_enrollable_paid_seat_price + + normalized_metadata_input = { + 'course_metadata': course_content.json_metadata, + 'course_run_metadata': course_content.json_metadata['course_runs'][0] + } + + serialized_data = NormalizedContentMetadataSerializer(normalized_metadata_input).data + + self.assertEqual(serialized_data['content_price'], expected_content_price)