Merge pull request #15811 from edx/schen/LEARNER-2222
Stop audit and honor mode creating basket and order
This commit is contained in:
@@ -15,7 +15,7 @@ from django.test.utils import override_settings
|
||||
from edx_rest_api_client import exceptions
|
||||
from nose.plugins.attrib import attr
|
||||
|
||||
from commerce.api.v0.views import SAILTHRU_CAMPAIGN_COOKIE
|
||||
from commerce.api.v0.views import SAILTHRU_CAMPAIGN_COOKIE, STOP_BASKET_CREATION_FLAG
|
||||
from commerce.constants import Messages
|
||||
from commerce.tests import TEST_BASKET_ID, TEST_ORDER_NUMBER, TEST_PAYMENT_DATA
|
||||
from commerce.tests.mocks import mock_basket_order, mock_create_basket
|
||||
@@ -23,6 +23,7 @@ from commerce.tests.test_views import UserMixin
|
||||
from course_modes.models import CourseMode
|
||||
from enrollment.api import get_enrollment
|
||||
from openedx.core.djangoapps.embargo.test_utils import restrict_course
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
|
||||
from openedx.core.lib.django_test_client_utils import get_absolute_url
|
||||
from student.models import CourseEnrollment
|
||||
from student.tests.factories import CourseModeFactory
|
||||
@@ -192,6 +193,7 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
cookie_name=UTM_COOKIE_NAME, cookie_contents=json.dumps(UTM_COOKIE_CONTENTS))
|
||||
self.assertIn(cookie_string, httpretty.last_request().headers['cookie'])
|
||||
|
||||
@override_waffle_flag(STOP_BASKET_CREATION_FLAG, active=False)
|
||||
@ddt.data(True, False)
|
||||
def test_course_with_honor_seat_sku(self, user_is_active):
|
||||
"""
|
||||
@@ -214,6 +216,7 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
# Test that call with cookie passes cookie along
|
||||
self._test_successful_ecommerce_api_call(utm_tracking_present=True)
|
||||
|
||||
@override_waffle_flag(STOP_BASKET_CREATION_FLAG, active=False)
|
||||
@ddt.data(True, False)
|
||||
def test_course_with_paid_seat_sku(self, user_is_active):
|
||||
"""
|
||||
@@ -228,6 +231,27 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
with mock_create_basket(response=return_value):
|
||||
self._test_successful_ecommerce_api_call(is_completed=False)
|
||||
|
||||
@override_waffle_flag(STOP_BASKET_CREATION_FLAG, active=True)
|
||||
@ddt.data(True, False)
|
||||
def test_course_without_creating_order(self, user_is_active):
|
||||
"""
|
||||
If the course has a SKU, and the STOP_BASKET_CREATION waffle flag is on,
|
||||
the enrollment should happen without contacting ecommerce api
|
||||
"""
|
||||
# Set user's active flag
|
||||
self.user.is_active = user_is_active
|
||||
self.user.save() # pylint: disable=no-member
|
||||
with mock_create_basket(expect_called=False):
|
||||
response = self._post_to_view()
|
||||
|
||||
# Validate the response content
|
||||
self.assertEqual(response.status_code, 200)
|
||||
msg = Messages.ENROLL_DIRECTLY.format(
|
||||
course_id=self.course.id,
|
||||
username=self.user.username
|
||||
)
|
||||
self.assertResponseMessage(response, msg)
|
||||
|
||||
def _test_course_without_sku(self, enrollment_mode=CourseMode.DEFAULT_MODE_SLUG):
|
||||
"""
|
||||
Validates the view bypasses the E-Commerce API when the course has no CourseModes with SKUs.
|
||||
|
||||
@@ -13,6 +13,7 @@ from rest_framework.views import APIView
|
||||
from commerce.constants import Messages
|
||||
from commerce.exceptions import InvalidResponseError
|
||||
from commerce.http import DetailResponse, InternalRequestErrorResponse
|
||||
from commerce.utils import COMMERCE_API_WAFFLE_FLAG_NAMESPACE
|
||||
from course_modes.models import CourseMode
|
||||
from courseware import courses
|
||||
from enrollment.api import add_enrollment
|
||||
@@ -20,6 +21,7 @@ from enrollment.views import EnrollmentCrossDomainSessionAuth
|
||||
from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
|
||||
from openedx.core.djangoapps.embargo import api as embargo_api
|
||||
from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleFlag
|
||||
from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiveUser
|
||||
from openedx.core.lib.log_utils import audit_log
|
||||
from student.models import CourseEnrollment, RegistrationCookieConfiguration
|
||||
@@ -27,6 +29,7 @@ from util.json_request import JsonResponse
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
SAILTHRU_CAMPAIGN_COOKIE = 'sailthru_bid'
|
||||
STOP_BASKET_CREATION_FLAG = WaffleFlag(COMMERCE_API_WAFFLE_FLAG_NAMESPACE, 'stop_basket_creation')
|
||||
|
||||
|
||||
class BasketsView(APIView):
|
||||
@@ -82,7 +85,7 @@ class BasketsView(APIView):
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
Attempt to create the basket and enroll the user.
|
||||
Attempt to enroll the user, and if needed, create the basket.
|
||||
"""
|
||||
user = request.user
|
||||
valid, course_key, error = self._is_data_valid(request)
|
||||
@@ -121,26 +124,49 @@ class BasketsView(APIView):
|
||||
if not default_enrollment_mode:
|
||||
msg = Messages.NO_DEFAULT_ENROLLMENT_MODE.format(course_id=course_id)
|
||||
return DetailResponse(msg, status=HTTP_406_NOT_ACCEPTABLE)
|
||||
elif default_enrollment_mode and not default_enrollment_mode.sku:
|
||||
# If there are no course modes with SKUs, enroll the user without contacting the external API.
|
||||
msg = Messages.NO_SKU_ENROLLED.format(
|
||||
enrollment_mode=default_enrollment_mode.slug,
|
||||
course_id=course_id,
|
||||
username=user.username
|
||||
elif not default_enrollment_mode.sku or STOP_BASKET_CREATION_FLAG.is_enabled():
|
||||
msg = Messages.ENROLL_DIRECTLY.format(
|
||||
username=user.username,
|
||||
course_id=course_id
|
||||
)
|
||||
if not default_enrollment_mode.sku:
|
||||
# If there are no course modes with SKUs, return a different message.
|
||||
msg = Messages.NO_SKU_ENROLLED.format(
|
||||
enrollment_mode=default_enrollment_mode.slug,
|
||||
course_id=course_id,
|
||||
username=user.username
|
||||
)
|
||||
log.info(msg)
|
||||
self._enroll(course_key, user, default_enrollment_mode.slug)
|
||||
self._handle_marketing_opt_in(request, course_key, user)
|
||||
return DetailResponse(msg)
|
||||
else:
|
||||
return self._create_basket_to_order(request, user, course_key, default_enrollment_mode)
|
||||
|
||||
def _add_request_cookie_to_api_session(self, server_session, request, cookie_name):
|
||||
""" Add cookie from user request into server session """
|
||||
user_cookie = None
|
||||
if cookie_name:
|
||||
user_cookie = request.COOKIES.get(cookie_name)
|
||||
if user_cookie:
|
||||
server_cookie = {cookie_name: user_cookie}
|
||||
if server_session.cookies:
|
||||
requests.utils.add_dict_to_cookiejar(server_session.cookies, server_cookie)
|
||||
else:
|
||||
server_session.cookies = requests.utils.cookiejar_from_dict(server_cookie)
|
||||
|
||||
def _create_basket_to_order(self, request, user, course_key, default_enrollment_mode):
|
||||
"""
|
||||
Connect to the ecommerce service to create the basket and the order to do the enrollment
|
||||
"""
|
||||
# Setup the API
|
||||
|
||||
course_id = unicode(course_key)
|
||||
try:
|
||||
api_session = requests.Session()
|
||||
api = ecommerce_api_client(user, session=api_session)
|
||||
except ValueError:
|
||||
self._enroll(course_key, user)
|
||||
msg = Messages.NO_ECOM_API.format(username=user.username, course_id=unicode(course_key))
|
||||
msg = Messages.NO_ECOM_API.format(username=user.username, course_id=course_id)
|
||||
log.debug(msg)
|
||||
return DetailResponse(msg)
|
||||
|
||||
@@ -191,18 +217,6 @@ class BasketsView(APIView):
|
||||
self._handle_marketing_opt_in(request, course_key, user)
|
||||
return response
|
||||
|
||||
def _add_request_cookie_to_api_session(self, server_session, request, cookie_name):
|
||||
""" Add cookie from user request into server session """
|
||||
user_cookie = None
|
||||
if cookie_name:
|
||||
user_cookie = request.COOKIES.get(cookie_name)
|
||||
if user_cookie:
|
||||
server_cookie = {cookie_name: user_cookie}
|
||||
if server_session.cookies:
|
||||
requests.utils.add_dict_to_cookiejar(server_session.cookies, server_cookie)
|
||||
else:
|
||||
server_session.cookies = requests.utils.cookiejar_from_dict(server_cookie)
|
||||
|
||||
|
||||
class BasketOrderView(APIView):
|
||||
""" Retrieve the order associated with a basket. """
|
||||
|
||||
@@ -12,6 +12,7 @@ class Messages(object):
|
||||
""" Strings used to populate response messages. """
|
||||
NO_ECOM_API = u'E-Commerce API not setup. Enrolled {username} in {course_id} directly.'
|
||||
NO_SKU_ENROLLED = u'The {enrollment_mode} mode for {course_id} does not have a SKU. Enrolling {username} directly.'
|
||||
ENROLL_DIRECTLY = u'Enroll {username} in {course_id} directly because no need for E-Commerce baskets and orders.'
|
||||
ORDER_COMPLETED = u'Order {order_number} was completed.'
|
||||
ORDER_INCOMPLETE_ENROLLED = u'Order {order_number} was created, but is not yet complete. User was enrolled.'
|
||||
NO_HONOR_MODE = u'Course {course_id} does not have an honor mode.'
|
||||
|
||||
@@ -7,6 +7,9 @@ from django.conf import settings
|
||||
|
||||
from commerce.models import CommerceConfiguration
|
||||
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
|
||||
from openedx.core.djangoapps.waffle_utils import WaffleFlagNamespace
|
||||
|
||||
COMMERCE_API_WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='commerce_api')
|
||||
|
||||
|
||||
def is_account_activation_requirement_disabled():
|
||||
|
||||
@@ -208,7 +208,7 @@ class WaffleFlagNamespace(WaffleNamespace):
|
||||
"""
|
||||
# validate arguments
|
||||
namespaced_flag_name = self._namespaced_name(flag_name)
|
||||
|
||||
value = None
|
||||
if check_before_waffle_callback:
|
||||
value = check_before_waffle_callback(namespaced_flag_name)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user