示例#1
0
    def test_flush_with_product_is_not_tracked_for_temporary_basket_calculation(
            self):
        """
        Verify the method does NOT fire 'Product Removed' Segment for temporary basket calculation
        """
        basket = self._create_basket_with_product()
        RequestCache.set(TEMPORARY_BASKET_CACHE_KEY, True)

        with mock.patch.object(Client, 'track') as mock_track:
            basket.flush()
            mock_track.assert_not_called()
示例#2
0
    def test_get_cached_response_force_django_cache_miss(self, mock_cache_get):
        RequestCache.set(SHOULD_FORCE_CACHE_MISS_KEY, True)
        mock_cache_get.return_value = EXPECTED_VALUE
        cached_response = TieredCache.get_cached_response(TEST_KEY)
        self.assertTrue(cached_response.is_miss)

        cached_response = RequestCache.get_cached_response(TEST_KEY)
        self.assertTrue(
            cached_response.is_miss,
            'Forced Django cache miss should not cache value in request cache.'
        )
示例#3
0
    def test_delete(self):
        RequestCache.set(TEST_KEY, EXPECTED_VALUE)
        RequestCache.set(TEST_KEY_2, EXPECTED_VALUE)
        RequestCache.delete(TEST_KEY)

        cached_response = RequestCache.get_cached_response(TEST_KEY)
        self.assertTrue(cached_response.is_miss)

        cached_response = RequestCache.get_cached_response(TEST_KEY_2)
        self.assertTrue(cached_response.is_hit)
        self.assertEqual(cached_response.value, EXPECTED_VALUE)
示例#4
0
 def test_add_product_not_tracked_for_temporary_basket_calculation(self):
     """
     Verify the method does NOT fire Product Added analytic event when a product is added to the basket
     """
     course = CourseFactory()
     basket = create_basket(empty=True)
     seat = course.create_or_update_seat('verified', True, 100,
                                         self.partner)
     RequestCache.set(TEMPORARY_BASKET_CACHE_KEY, True)
     with mock.patch(
             'ecommerce.extensions.basket.models.track_segment_event'
     ) as mock_track:
         basket.add_product(seat)
         properties = translate_basket_line_for_segment(
             basket.lines.first())
         properties['cart_id'] = basket.id
         mock_track.assert_not_called()
示例#5
0
    def get(self, request):  # pylint: disable=too-many-statements
        """ Calculate basket totals given a list of sku's

        Create a temporary basket add the sku's and apply an optional voucher code.
        Then calculate the total price less discounts. If a voucher code is not
        provided apply a voucher in the Enterprise entitlements available
        to the user.

        Query Params:
            sku (string): A list of sku(s) to calculate
            code (string): Optional voucher code to apply to the basket.
            username (string): Optional username of a user for which to calculate the basket.

        Returns:
            JSON: {
                    'total_incl_tax_excl_discounts': basket.total_incl_tax_excl_discounts,
                    'total_incl_tax': basket.total_incl_tax,
                    'currency': basket.currency
                }
        """
        RequestCache.set(TEMPORARY_BASKET_CACHE_KEY,
                         True)  # TODO: LEARNER 5463

        partner = get_partner_for_site(request)
        skus = request.GET.getlist('sku')
        if not skus:
            return HttpResponseBadRequest(_('No SKUs provided.'))
        skus.sort()

        code = request.GET.get('code', None)
        try:
            voucher = Voucher.objects.get(code=code) if code else None
        except Voucher.DoesNotExist:
            voucher = None

        products = Product.objects.filter(stockrecords__partner=partner,
                                          stockrecords__partner_sku__in=skus)
        if not products:
            return HttpResponseBadRequest(
                _('Products with SKU(s) [{skus}] do not exist.').format(
                    skus=', '.join(skus)))

        # If there is only one product apply an Enterprise entitlement voucher
        if not voucher and len(products) == 1:
            voucher = get_entitlement_voucher(request, products[0])

        basket_owner = request.user

        requested_username = request.GET.get('username', default='')
        is_anonymous = request.GET.get('is_anonymous',
                                       'false').lower() == 'true'

        use_default_basket = is_anonymous

        # validate query parameters
        if requested_username and is_anonymous:
            return HttpResponseBadRequest(
                _('Provide username or is_anonymous query param, but not both')
            )
        elif not requested_username and not is_anonymous:
            logger.warning(
                "Request to Basket Calculate must supply either username or is_anonymous query"
                " param. Requesting user=%s. Future versions of this API will treat this "
                "WARNING as an ERROR and raise an exception.",
                basket_owner.username)
            requested_username = request.user.username

        # If a username is passed in, validate that the user has staff access or is the same user.
        if requested_username:
            if basket_owner.username.lower() == requested_username.lower():
                pass
            elif basket_owner.is_staff:
                try:
                    basket_owner = User.objects.get(
                        username=requested_username)
                except User.DoesNotExist:
                    # This case represents a user who is logged in to marketing, but
                    # doesn't yet have an account in ecommerce. These users have
                    # never purchased before.
                    use_default_basket = True
            else:
                return HttpResponseForbidden('Unauthorized user credentials')

        if basket_owner.username == self.MARKETING_USER and not use_default_basket:
            # For legacy requests that predate is_anonymous parameter, we will calculate
            # an anonymous basket if the calculated user is the marketing user.
            # TODO: LEARNER-5057: Remove this special case for the marketing user
            # once logs show no more requests with no parameters (see above).
            use_default_basket = True

        if use_default_basket:
            basket_owner = None

        cache_key = None
        if use_default_basket:
            # For an anonymous user we can directly get the cached price, because
            # there can't be any enrollments or entitlements.
            cache_key = get_cache_key(site_comain=request.site,
                                      resource_name='calculate',
                                      skus=skus)
            cached_response = TieredCache.get_cached_response(cache_key)
            if cached_response.is_hit:
                return Response(cached_response.value)

        if waffle.flag_is_active(
                request,
                "disable_calculate_temporary_basket_atomic_transaction"):
            response = self._calculate_temporary_basket(
                basket_owner, request, products, voucher, skus, code)
        else:
            response = self._calculate_temporary_basket_atomic(
                basket_owner, request, products, voucher, skus, code)

        if response and use_default_basket:
            TieredCache.set_all_tiers(
                cache_key, response,
                settings.ANONYMOUS_BASKET_CALCULATE_CACHE_TIMEOUT)

        return Response(response)
示例#6
0
 def test_get_cached_response_request_cache_hit(self):
     RequestCache.set(TEST_KEY, EXPECTED_VALUE)
     cached_response = TieredCache.get_cached_response(TEST_KEY)
     self.assertTrue(cached_response.is_hit)
     self.assertEqual(cached_response.value, EXPECTED_VALUE)
示例#7
0
 def test_clear(self):
     RequestCache.set(TEST_KEY, EXPECTED_VALUE)
     RequestCache.clear()
     cached_response = RequestCache.get_cached_response(TEST_KEY)
     self.assertTrue(cached_response.is_miss)
示例#8
0
 def test_get_cached_response_hit_with_cached_none(self):
     RequestCache.set(TEST_KEY, None)
     cached_response = RequestCache.get_cached_response(TEST_KEY)
     self.assertFalse(cached_response.is_miss)
     self.assertEqual(cached_response.value, None)
示例#9
0
 def test_get_cached_response_hit(self):
     RequestCache.set(TEST_KEY, EXPECTED_VALUE)
     cached_response = RequestCache.get_cached_response(TEST_KEY)
     self.assertFalse(cached_response.is_miss)
     self.assertEqual(cached_response.value, EXPECTED_VALUE)
示例#10
0
 def _dirty_request_cache():
     """ Dirties the request cache to ensure it is cleared later. """
     RequestCache.set(TEST_KEY, EXPECTED_VALUE)