This repository has been archived by the owner on May 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
views_custom.py
165 lines (139 loc) · 6.19 KB
/
views_custom.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
"""
The Discount API Views should return information about discounts that apply to the user and course.
"""
from django.http import HttpResponseBadRequest
from django.utils.decorators import method_decorator
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
from edx_toggles.toggles import WaffleFlag
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from rest_framework.response import Response
from rest_framework.views import APIView
from common.djangoapps.course_modes.models import get_cosmetic_verified_display_price
from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.track import segment
from lms.djangoapps.commerce.utils import EcommerceService
from lms.djangoapps.courseware.utils import can_show_verified_upgrade
from lms.djangoapps.experiments.stable_bucketing import stable_bucketing_hash_group
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from openedx.core.djangoapps.cors_csrf.decorators import ensure_csrf_cookie_cross_domain
from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
from openedx.core.lib.api.permissions import ApiKeyHeaderPermissionIsAuthenticated
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin
# .. toggle_name: experiments.mobile_upsell_rev934
# .. toggle_implementation: WaffleFlag
# .. toggle_default: False
# .. toggle_description: Toggle mobile upsell enabled
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2019-09-05
# .. toggle_target_removal_date: None
# .. toggle_tickets: REV-934
# .. toggle_warning: This temporary feature toggle does not have a target removal date.
MOBILE_UPSELL_FLAG = WaffleFlag('experiments.mobile_upsell_rev934', __name__)
MOBILE_UPSELL_EXPERIMENT = 'mobile_upsell_experiment'
class Rev934(DeveloperErrorViewMixin, APIView):
"""
**Use Cases**
Request upsell information for mobile app users
**Example Requests**
GET /api/experiments/v0/custom/REV-934/?course_id={course_key_string}
**Response Values**
Body consists of the following fields:
show_upsell:
whether to show upsell in the moble app in this case
price:
(optional) the price to show if show_upsell is true
basket_url:
(optional) the url to the checkout page with the course's sku if show_upsell is true
upsell_flag:
(optional) false if the upsell flag is off, not present otherwise
Response:
{
"show_upsell": true,
"price": "$199",
"basket_url": "https://ecommerce.edx.org/basket/add?sku=abcdef"
}
**Parameters:**
course_key_string:
The course key that may be upsold
**Returns**
* 200 on success with above fields.
* 401 if there is no user signed in.
Example response:
{
"show_upsell": true,
"price": "$199",
"basket_url": "https://ecommerce.edx.org/basket/add?sku=abcdef"
}
"""
# https://courses.stage.edx.org/api/experiments/v0/custom/REV-934/?course_id=course-v1%3AedX%2BDemoX%2BDemo_Course
authentication_classes = (
JwtAuthentication,
BearerAuthenticationAllowInactiveUser,
SessionAuthenticationAllowInactiveUser,
)
permission_classes = (ApiKeyHeaderPermissionIsAuthenticated,)
@method_decorator(ensure_csrf_cookie_cross_domain)
def get(self, request):
"""
Return the if the course should be upsold in the mobile app, if the user has appropriate permissions.
"""
if not MOBILE_UPSELL_FLAG.is_enabled():
return Response({
'show_upsell': False,
'upsell_flag': False,
})
course_id = request.GET.get('course_id')
try:
course_key = CourseKey.from_string(course_id)
except InvalidKeyError:
return HttpResponseBadRequest("Missing or invalid course_id")
course = CourseOverview.get_from_id(course_key)
if not course.has_started() or course.has_ended():
return Response({
'show_upsell': False,
'upsell_flag': MOBILE_UPSELL_FLAG.is_enabled(),
'course_running': False,
})
user = request.user
try:
enrollment = CourseEnrollment.objects.select_related(
'course'
).get(user_id=user.id, course_id=course.id)
user_upsell = can_show_verified_upgrade(user, enrollment)
except CourseEnrollment.DoesNotExist:
user_upsell = True
basket_url = EcommerceService().upgrade_url(user, course.id)
upgrade_price = str(get_cosmetic_verified_display_price(course))
could_upsell = bool(user_upsell and basket_url)
bucket = stable_bucketing_hash_group(MOBILE_UPSELL_EXPERIMENT, 2, user)
if could_upsell and hasattr(request, 'session') and MOBILE_UPSELL_EXPERIMENT not in request.session:
properties = {
'site': request.site.domain,
'app_label': 'experiments',
'bucket': bucket,
'experiment': 'REV-934',
}
segment.track(
user_id=user.id,
event_name='edx.bi.experiment.user.bucketed',
properties=properties,
)
# Mark that we've recorded this bucketing, so that we don't do it again this session
request.session[MOBILE_UPSELL_EXPERIMENT] = True
show_upsell = bool(bucket != 0 and could_upsell)
if show_upsell:
return Response({
'show_upsell': show_upsell,
'price': upgrade_price,
'basket_url': basket_url,
})
else:
return Response({
'show_upsell': show_upsell,
'upsell_flag': MOBILE_UPSELL_FLAG.is_enabled(),
'experiment_bucket': bucket,
'user_upsell': user_upsell,
'basket_url': basket_url,
})