From a19697786f843850a51271810feccb38263687b0 Mon Sep 17 00:00:00 2001 From: Juliana Kang Date: Mon, 22 Jul 2024 14:01:07 -0400 Subject: [PATCH] feat: Add First Purchase Discount override (#35143) REV-4098 --- .../outline/tests/test_view.py | 27 ++++++++++++++----- lms/envs/devstack.py | 3 +++ lms/envs/test.py | 3 +++ .../features/discounts/tests/test_utils.py | 14 ++++++++-- openedx/features/discounts/utils.py | 13 ++++++++- 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/lms/djangoapps/course_home_api/outline/tests/test_view.py b/lms/djangoapps/course_home_api/outline/tests/test_view.py index 4f40d9a80192..c092e9e2a506 100644 --- a/lms/djangoapps/course_home_api/outline/tests/test_view.py +++ b/lms/djangoapps/course_home_api/outline/tests/test_view.py @@ -11,6 +11,7 @@ import json # lint-amnesty, pylint: disable=wrong-import-order from completion.models import BlockCompletion from django.conf import settings # lint-amnesty, pylint: disable=wrong-import-order +from django.test import override_settings from django.urls import reverse # lint-amnesty, pylint: disable=wrong-import-order from edx_toggles.toggles.testutils import override_waffle_flag # lint-amnesty, pylint: disable=wrong-import-order @@ -33,7 +34,10 @@ DISPLAY_COURSE_SOCK_FLAG, ENABLE_COURSE_GOALS ) -from openedx.features.discounts.applicability import DISCOUNT_APPLICABILITY_FLAG +from openedx.features.discounts.applicability import ( + DISCOUNT_APPLICABILITY_FLAG, + FIRST_PURCHASE_DISCOUNT_OVERRIDE_FLAG +) from xmodule.course_block import COURSE_VISIBILITY_PUBLIC, COURSE_VISIBILITY_PUBLIC_OUTLINE # lint-amnesty, pylint: disable=wrong-import-order from xmodule.modulestore.tests.factories import CourseFactory, BlockFactory # lint-amnesty, pylint: disable=wrong-import-order @@ -179,17 +183,28 @@ def test_welcome_message(self, welcome_message_is_dismissed): welcome_message_html = self.client.get(self.url).data['welcome_message_html'] assert welcome_message_html == (None if welcome_message_is_dismissed else '

Welcome

') - def test_offer(self): + @ddt.data( + (False, 'EDXWELCOME'), + (True, 'NOTEDXWELCOME'), + ) + @ddt.unpack + def test_offer(self, is_fpd_override_waffle_flag_on, fpd_code): + """ + Test that the offer data contains the correct code for the first purchase discount, + which can be overriden via a waffle flag from the default EDXWELCOME. + """ CourseEnrollment.enroll(self.user, self.course.id) response = self.client.get(self.url) assert response.data['offer'] is None - with override_waffle_flag(DISCOUNT_APPLICABILITY_FLAG, active=True): - response = self.client.get(self.url) + with override_settings(FIRST_PURCHASE_DISCOUNT_OVERRIDE_CODE='NOTEDXWELCOME'): + with override_waffle_flag(DISCOUNT_APPLICABILITY_FLAG, active=True): + with override_waffle_flag(FIRST_PURCHASE_DISCOUNT_OVERRIDE_FLAG, active=is_fpd_override_waffle_flag_on): + response = self.client.get(self.url) - # Just a quick spot check that the dictionary looks like what we expect - assert response.data['offer']['code'] == 'EDXWELCOME' + # Just a quick spot check that the dictionary looks like what we expect + assert response.data['offer']['code'] == fpd_code def test_access_expiration(self): enrollment = CourseEnrollment.enroll(self.user, self.course.id, CourseMode.VERIFIED) diff --git a/lms/envs/devstack.py b/lms/envs/devstack.py index 611017962852..7de34f9146e0 100644 --- a/lms/envs/devstack.py +++ b/lms/envs/devstack.py @@ -239,6 +239,9 @@ def should_show_debug_toolbar(request): # lint-amnesty, pylint: disable=missing ########################## Authn MFE Context API ####################### ENABLE_DYNAMIC_REGISTRATION_FIELDS = True +########################## Discount/Coupons ####################### +FIRST_PURCHASE_DISCOUNT_OVERRIDE_CODE = '' + ############## ECOMMERCE API CONFIGURATION SETTINGS ############### ECOMMERCE_PUBLIC_URL_ROOT = 'http://localhost:18130' ECOMMERCE_API_URL = 'http://edx.devstack.ecommerce:18130/api/v2' diff --git a/lms/envs/test.py b/lms/envs/test.py index 3c4bb9564927..2a41e5499060 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -92,6 +92,9 @@ # Enable a parental consent age limit for testing PARENTAL_CONSENT_AGE_LIMIT = 13 +# Enable First Purchase Discount offer override +FIRST_PURCHASE_DISCOUNT_OVERRIDE_CODE = '' + # Local Directories TEST_ROOT = path("test_root") # Want static files in the same dir for running on jenkins. diff --git a/openedx/features/discounts/tests/test_utils.py b/openedx/features/discounts/tests/test_utils.py index 1ff305831d74..d91d61839c8b 100644 --- a/openedx/features/discounts/tests/test_utils.py +++ b/openedx/features/discounts/tests/test_utils.py @@ -5,7 +5,7 @@ import ddt from django.contrib.auth.models import AnonymousUser -from django.test import TestCase +from django.test import TestCase, override_settings from django.utils.translation import override as override_lang from edx_toggles.toggles.testutils import override_waffle_flag @@ -14,7 +14,11 @@ from common.djangoapps.student.models import CourseEnrollment from common.djangoapps.student.tests.factories import UserFactory from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory -from openedx.features.discounts.applicability import DISCOUNT_APPLICABILITY_FLAG, get_discount_expiration_date +from openedx.features.discounts.applicability import ( + DISCOUNT_APPLICABILITY_FLAG, + FIRST_PURCHASE_DISCOUNT_OVERRIDE_FLAG, + get_discount_expiration_date +) from .. import utils @@ -84,6 +88,12 @@ def test_spanish_code(self): with override_lang('es-419'): assert utils.generate_offer_data(self.user, self.overview)['code'] == 'BIENVENIDOAEDX' + def test_override(self): + with override_settings(FIRST_PURCHASE_DISCOUNT_OVERRIDE_CODE='NOTEDXWELCOME'): + with override_waffle_flag(DISCOUNT_APPLICABILITY_FLAG, active=True): + with override_waffle_flag(FIRST_PURCHASE_DISCOUNT_OVERRIDE_FLAG, active=True): + assert utils.generate_offer_data(self.user, self.overview)['code'] == 'NOTEDXWELCOME' + def test_anonymous(self): assert utils.generate_offer_data(AnonymousUser(), self.overview) is None diff --git a/openedx/features/discounts/utils.py b/openedx/features/discounts/utils.py index f52f821d9a9d..e97524d4381a 100644 --- a/openedx/features/discounts/utils.py +++ b/openedx/features/discounts/utils.py @@ -5,6 +5,7 @@ from datetime import datetime import pytz +from django.conf import settings from django.utils.translation import get_language from django.utils.translation import gettext as _ @@ -13,6 +14,7 @@ from lms.djangoapps.courseware.utils import verified_upgrade_deadline_link from openedx.core.djangolib.markup import HTML from openedx.features.discounts.applicability import ( + FIRST_PURCHASE_DISCOUNT_OVERRIDE_FLAG, REV1008_EXPERIMENT_ID, can_receive_discount, discount_percentage, @@ -98,8 +100,17 @@ def generate_offer_data(user, course): original, discounted, percentage = _get_discount_prices(user, course, assume_discount=True) + # Override the First Purchase Discount to another code only if flag is enabled + first_purchase_discount_code = 'BIENVENIDOAEDX' if get_language() == 'es-419' else 'EDXWELCOME' + if FIRST_PURCHASE_DISCOUNT_OVERRIDE_FLAG.is_enabled(): + first_purchase_discount_code = getattr( + settings, + 'FIRST_PURCHASE_DISCOUNT_OVERRIDE_CODE', + first_purchase_discount_code + ) + return { - 'code': 'BIENVENIDOAEDX' if get_language() == 'es-419' else 'EDXWELCOME', + 'code': first_purchase_discount_code, 'expiration_date': expiration_date, 'original_price': original, 'discounted_price': discounted,