diff --git a/lms/djangoapps/course_home_api/course_metadata/tests/test_views.py b/lms/djangoapps/course_home_api/course_metadata/tests/test_views.py index 6ffa15852991f6c081d4c99ae0af36eb18a4b992..7430f5cc624f573343cb3d26b08107b677eccdb3 100644 --- a/lms/djangoapps/course_home_api/course_metadata/tests/test_views.py +++ b/lms/djangoapps/course_home_api/course_metadata/tests/test_views.py @@ -16,8 +16,7 @@ from lms.djangoapps.courseware.toggles import ( from common.djangoapps.student.models import CourseEnrollment from common.djangoapps.student.tests.factories import UserFactory from lms.djangoapps.course_home_api.tests.utils import BaseCourseHomeTests -from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag -from lms.djangoapps.experiments.utils import STREAK_DISCOUNT_EXPERIMENT_FLAG +from lms.djangoapps.experiments.utils import STREAK_DISCOUNT_FLAG @ddt.ddt @@ -86,12 +85,12 @@ class CourseHomeMetadataTests(BaseCourseHomeTests): def test_streak_data_in_response(self): """ Test that metadata endpoint returns data for the streak celebration """ CourseEnrollment.enroll(self.user, self.course.id, 'audit') - with override_experiment_waffle_flag(STREAK_DISCOUNT_EXPERIMENT_FLAG, active=True): + with override_waffle_flag(STREAK_DISCOUNT_FLAG, active=True): with mock.patch('common.djangoapps.student.models.UserCelebration.perform_streak_updates', return_value=3): response = self.client.get(self.url, content_type='application/json') celebrations = response.json()['celebrations'] assert celebrations['streak_length_to_celebrate'] == 3 - assert celebrations['streak_discount_experiment_enabled'] is True + assert celebrations['streak_discount_enabled'] is True @ddt.data( # Who has access to MFE courseware? diff --git a/lms/djangoapps/experiments/flags.py b/lms/djangoapps/experiments/flags.py index d776fb222731d48defdb3f54554b3951224b41f9..323100f849afa2c2dc89a5556387ab70df9c2c63 100644 --- a/lms/djangoapps/experiments/flags.py +++ b/lms/djangoapps/experiments/flags.py @@ -11,7 +11,6 @@ from crum import get_current_request from edx_django_utils.cache import RequestCache from common.djangoapps.track import segment -from common.djangoapps.course_modes.models import CourseMode from lms.djangoapps.experiments.stable_bucketing import stable_bucketing_hash_group from openedx.core.djangoapps.waffle_utils import CourseWaffleFlag @@ -266,21 +265,6 @@ class ExperimentWaffleFlag(CourseWaffleFlag): # Mark that we've recorded this bucketing, so that we don't do it again this session request.session[session_key] = True - # Temporary event for AA-759 experiment - if course_key and self._experiment_name == 'discount_experiment_AA759': - modes_dict = CourseMode.modes_for_course_dict(course_id=course_key, include_expired=False) - verified_mode = modes_dict.get('verified', None) - if verified_mode: - segment.track( - user_id=user.id, - event_name='edx.bi.experiment.AA759.bucketed', - properties={ - 'course_id': str(course_key), - 'bucket': bucket, - 'sku': verified_mode.sku, - } - ) - return self._cache_bucket(experiment_name, bucket) def is_enabled(self, course_key=None): diff --git a/lms/djangoapps/experiments/utils.py b/lms/djangoapps/experiments/utils.py index 6252215cf8fb01d5e18b60754734e96e41f755c5..dc5aaa6047e689c0cbc7d8360cc40732f2c68c43 100644 --- a/lms/djangoapps/experiments/utils.py +++ b/lms/djangoapps/experiments/utils.py @@ -7,7 +7,7 @@ import logging from decimal import Decimal from django.utils.timezone import now -from edx_toggles.toggles import LegacyWaffleFlag, LegacyWaffleFlagNamespace +from edx_toggles.toggles import WaffleFlag from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey @@ -17,7 +17,6 @@ from common.djangoapps.student.models import CourseEnrollment from lms.djangoapps.commerce.utils import EcommerceService from lms.djangoapps.courseware.access import has_staff_access_to_preview_mode from lms.djangoapps.courseware.utils import can_show_verified_upgrade, verified_upgrade_deadline_link -from lms.djangoapps.experiments.flags import ExperimentWaffleFlag from openedx.core.djangoapps.catalog.utils import get_programs from openedx.core.djangoapps.django_comment_common.models import Role from openedx.core.djangoapps.schedules.models import Schedule @@ -28,8 +27,6 @@ logger = logging.getLogger(__name__) # TODO: clean up as part of REVEM-199 (START) -experiments_namespace = LegacyWaffleFlagNamespace(name='experiments') - # .. toggle_name: experiments.add_programs # .. toggle_implementation: WaffleFlag # .. toggle_default: False @@ -39,10 +36,9 @@ experiments_namespace = LegacyWaffleFlagNamespace(name='experiments') # .. toggle_target_removal_date: None # .. toggle_tickets: REVEM-63, REVEM-198 # .. toggle_warnings: This temporary feature toggle does not have a target removal date. -PROGRAM_INFO_FLAG = LegacyWaffleFlag( - waffle_namespace=experiments_namespace, - flag_name='add_programs', - module_name=__name__, +PROGRAM_INFO_FLAG = WaffleFlag( + 'experiments.add_programs', + __name__, ) # .. toggle_name: experiments.add_dashboard_info @@ -54,7 +50,7 @@ PROGRAM_INFO_FLAG = LegacyWaffleFlag( # .. toggle_target_removal_date: None # .. toggle_tickets: REVEM-118 # .. toggle_warnings: This temporary feature toggle does not have a target removal date. -DASHBOARD_INFO_FLAG = LegacyWaffleFlag(experiments_namespace, 'add_dashboard_info', __name__) +DASHBOARD_INFO_FLAG = WaffleFlag('experiments.add_dashboard_info', __name__) # TODO END: clean up as part of REVEM-199 (End) # TODO: Clean up as part of REV-1205 (START) @@ -67,27 +63,24 @@ DASHBOARD_INFO_FLAG = LegacyWaffleFlag(experiments_namespace, 'add_dashboard_inf # .. toggle_target_removal_date: None # .. toggle_tickets: REV-1205 # .. toggle_warnings: This temporary feature toggle does not have a target removal date. -UPSELL_TRACKING_FLAG = LegacyWaffleFlag( - waffle_namespace=experiments_namespace, - flag_name='add_upsell_tracking', - module_name=__name__, +UPSELL_TRACKING_FLAG = WaffleFlag( + 'experiments.add_upsell_tracking', + __name__, ) # TODO END: Clean up as part of REV-1205 (End) -# .. toggle_name: streak_celebration.discount_experiment_AA759 -# .. toggle_implementation: ExperimentWaffleFlag +# .. toggle_name: streak_celebration.streak_discount_enabled +# .. toggle_implementation: WaffleFlag # .. toggle_default: False -# .. toggle_description: This experiment flag enables an engagement discount incentive message. +# .. toggle_description: This flag enables an engagement discount incentive message. # .. toggle_warnings: This flag depends on the streak celebration feature being enabled -# .. toggle_use_cases: temporary -# .. toggle_creation_date: 2021-05-05 -# .. toggle_target_removal_date: 2021-07-05 -# .. toggle_tickets: https://openedx.atlassian.net/browse/AA-759 -STREAK_DISCOUNT_EXPERIMENT_FLAG = ExperimentWaffleFlag( - LegacyWaffleFlagNamespace(name='streak_celebration'), - 'discount_experiment_AA759', +# .. toggle_use_cases: opt_out, open_edx +# .. toggle_creation_date: 2021-08-26 +# .. toggle_target_removal_date: None +# .. toggle_tickets: https://openedx.atlassian.net/browse/AA-950 +STREAK_DISCOUNT_FLAG = WaffleFlag( + 'streak_celebration.streak_discount_enabled', __name__, - use_course_aware_bucketing=False ) diff --git a/openedx/core/djangoapps/courseware_api/tests/pacts/api-courseware-contract.json b/openedx/core/djangoapps/courseware_api/tests/pacts/api-courseware-contract.json index 8c192931bff5b1afee02b12f2ab6edf26be291a8..733477e0ad52c9ec4b1862b5d392a6f75d757c78 100644 --- a/openedx/core/djangoapps/courseware_api/tests/pacts/api-courseware-contract.json +++ b/openedx/core/djangoapps/courseware_api/tests/pacts/api-courseware-contract.json @@ -88,7 +88,7 @@ "celebrations": { "first_section": false, "streak_length_to_celebrate": null, - "streak_discount_experiment_enabled": false + "streak_discount_enabled": false }, "user_has_passing_grade": false, "course_exit_page_is_active": false, @@ -223,7 +223,7 @@ "$.body.celebrations.irst_section": { "match": "type" }, - "$.body.celebrations.streak_discount_experiment_enabled": { + "$.body.celebrations.streak_discount_enabled": { "match": "type" }, "$.body.user_has_passing_grade": { diff --git a/openedx/core/djangoapps/courseware_api/tests/test_views.py b/openedx/core/djangoapps/courseware_api/tests/test_views.py index 64d27106532d5e651dde11a6236edfcc56d61047..d3b463af10ec69cb118ad37c381dbb56b2941b1d 100644 --- a/openedx/core/djangoapps/courseware_api/tests/test_views.py +++ b/openedx/core/djangoapps/courseware_api/tests/test_views.py @@ -29,8 +29,7 @@ from lms.djangoapps.courseware.toggles import ( COURSEWARE_MICROFRONTEND_SPECIAL_EXAMS, COURSEWARE_MICROFRONTEND_PROCTORED_EXAMS, ) -from lms.djangoapps.experiments.testutils import override_experiment_waffle_flag -from lms.djangoapps.experiments.utils import STREAK_DISCOUNT_EXPERIMENT_FLAG +from lms.djangoapps.experiments.utils import STREAK_DISCOUNT_FLAG from lms.djangoapps.verify_student.services import IDVerificationService from common.djangoapps.student.models import ( CourseEnrollment, CourseEnrollmentCelebration @@ -302,12 +301,12 @@ class CourseApiTestViews(BaseCoursewareTests, MasqueradeMixin): def test_streak_data_in_response(self): """ Test that metadata endpoint returns data for the streak celebration """ CourseEnrollment.enroll(self.user, self.course.id, 'audit') - with override_experiment_waffle_flag(STREAK_DISCOUNT_EXPERIMENT_FLAG, active=True): + with override_waffle_flag(STREAK_DISCOUNT_FLAG, active=True): with mock.patch('common.djangoapps.student.models.UserCelebration.perform_streak_updates', return_value=3): response = self.client.get(self.url, content_type='application/json') celebrations = response.json()['celebrations'] assert celebrations['streak_length_to_celebrate'] == 3 - assert celebrations['streak_discount_experiment_enabled'] is True + assert celebrations['streak_discount_enabled'] is True @ddt.data( (False, False), diff --git a/openedx/core/djangoapps/courseware_api/utils.py b/openedx/core/djangoapps/courseware_api/utils.py index 0ecbcf57e61316cb4d821b4de7ff410c452ac163..fcd0ba3e5d39333d936495803945730bf56c3eb6 100644 --- a/openedx/core/djangoapps/courseware_api/utils.py +++ b/openedx/core/djangoapps/courseware_api/utils.py @@ -7,9 +7,10 @@ from babel.numbers import get_currency_symbol from common.djangoapps.course_modes.models import CourseMode from common.djangoapps.student.models import CourseEnrollmentCelebration, UserCelebration from lms.djangoapps.courseware.utils import can_show_verified_upgrade, verified_upgrade_deadline_link -from lms.djangoapps.experiments.utils import STREAK_DISCOUNT_EXPERIMENT_FLAG +from lms.djangoapps.experiments.utils import STREAK_DISCOUNT_FLAG from openedx.features.course_duration_limits.access import get_user_course_expiration_date -from openedx.features.discounts.applicability import can_show_streak_discount_experiment_coupon +from openedx.features.discounts.applicability import can_show_streak_discount_coupon +from common.djangoapps.track import segment def get_celebrations_dict(user, enrollment, course, browser_timezone): @@ -20,7 +21,7 @@ def get_celebrations_dict(user, enrollment, course, browser_timezone): return { 'first_section': False, 'streak_length_to_celebrate': None, - 'streak_discount_experiment_enabled': False, + 'streak_discount_enabled': False, } streak_length_to_celebrate = UserCelebration.perform_streak_updates( @@ -29,15 +30,29 @@ def get_celebrations_dict(user, enrollment, course, browser_timezone): celebrations = { 'first_section': CourseEnrollmentCelebration.should_celebrate_first_section(enrollment), 'streak_length_to_celebrate': streak_length_to_celebrate, - 'streak_discount_experiment_enabled': False, + 'streak_discount_enabled': False, } - # We only want to bucket people into the AA-759 experiment if they are going to see the streak celebration if streak_length_to_celebrate: - # We only want to bucket people into the AA-759 experiment + # We only want to offer the streak discount # if the course has not ended, is upgradeable and the user is not an enterprise learner - if can_show_streak_discount_experiment_coupon(user, course): - celebrations['streak_discount_experiment_enabled'] = STREAK_DISCOUNT_EXPERIMENT_FLAG.is_enabled(course.id) + if can_show_streak_discount_coupon(user, course): + celebrations['streak_discount_enabled'] = STREAK_DISCOUNT_FLAG.is_enabled() + + # Send course streak coupon event + course_key = str(course.id) + modes_dict = CourseMode.modes_for_course_dict(course_id=course_key, include_expired=False) + verified_mode = modes_dict.get('verified', None) + if verified_mode: + segment.track( + user_id=user.id, + event_name='edx.bi.course.streak_discount_enabled', + properties={ + 'course_id': str(course_key), + 'sku': verified_mode.sku, + } + ) + return celebrations diff --git a/openedx/features/discounts/applicability.py b/openedx/features/discounts/applicability.py index f9f48908cf86811bc2cec3170c1a571388307fcf..a697e50af29553a87d934f401d5e97fe3c9676e2 100644 --- a/openedx/features/discounts/applicability.py +++ b/openedx/features/discounts/applicability.py @@ -83,10 +83,10 @@ def get_discount_expiration_date(user, course): return discount_expiration_date -def can_show_streak_discount_experiment_coupon(user, course): +def can_show_streak_discount_coupon(user, course): """ Check whether this combination of user and course - can receive the AA-759 experiment discount. + can receive the streak discount. """ # Course end date needs to be in the future if course.has_ended():