Пример #1
0
    def test_is_entitlement_expired_cached(self):
        """
        Test that entitlement's expired status gets cached

        We expect 2 calls to set_all_tiers in the is_entitlement_expired
        method due to:
            - the site_configuration api setup
            - the result being cached
        """
        self.mock_access_token_response()

        self.course_entitlement.expires = EXPIRED_DATE
        httpretty.register_uri(httpretty.GET,
                               get_lms_entitlement_api_url() +
                               'entitlements/' + self.course_entitlement_uuid +
                               '/',
                               status=200,
                               body=json.dumps({}),
                               content_type='application/json')

        with mock.patch.object(
                TieredCache, 'set_all_tiers',
                wraps=TieredCache.set_all_tiers) as mocked_set_all_tiers:
            mocked_set_all_tiers.assert_not_called()

            _ = UserAlreadyPlacedOrder.is_entitlement_expired(
                self.course_entitlement_uuid, site=self.site)
            self.assertEqual(mocked_set_all_tiers.call_count, 2)

            _ = UserAlreadyPlacedOrder.is_entitlement_expired(
                self.course_entitlement_uuid, site=self.site)
            self.assertEqual(mocked_set_all_tiers.call_count, 2)
Пример #2
0
    def test_no_previous_order(self):
        """
        Test the case that user do not have any previous order for the product.
        """
        user = self.create_user()
        self.assertFalse(
            UserAlreadyPlacedOrder.user_already_placed_order(
                user=user, product=self.product, site=self.site))

        self.assertFalse(
            UserAlreadyPlacedOrder.user_already_placed_order(
                user=user, product=self.course_entitlement, site=self.site))
Пример #3
0
 def test_already_expired_entitlement_order(self):
     """
     Test the case that user has a non refunded order for the course entitlement
     """
     self.mock_access_token_response()
     body = {
         "user": "******",
         "uuid": "adfca7da-e593-428b-b12d-f728e2dd220d",
         "course_uuid": "b084097a-7596-4fe6-b6a2-d335bffeb3f1",
         "expired_at": None,
         "created": "2017-12-16T21:35:59.402622Z",
         "modified": "2017-12-16T21:36:19.280197Z",
         "mode": "verified",
         "order_number": "EDX-100014"
     }
     httpretty.register_uri(httpretty.GET,
                            get_lms_entitlement_api_url() +
                            'entitlements/' + self.course_entitlement_uuid +
                            '/',
                            status=200,
                            body=json.dumps(body),
                            content_type='application/json')
     self.assertTrue(
         UserAlreadyPlacedOrder.user_already_placed_order(
             user=self.user,
             product=self.course_entitlement,
             site=self.site))
Пример #4
0
 def test_already_have_not_refunded_order(self):
     """
     Test the case that user have a non refunded order for the product.
     """
     self.assertTrue(
         UserAlreadyPlacedOrder.user_already_placed_order(
             user=self.user, product=self.product, site=self.site))
Пример #5
0
 def test_is_order_line_refunded(self, refund_line_status, is_refunded):
     """
     Tests the functionality of is_order_line_refunded method.
     """
     user = self.create_user()
     refund = RefundFactory(user=user)
     refund_line = RefundLine.objects.get(refund=refund)
     refund_line.status = refund_line_status
     refund_line.save()
     self.assertEqual(
         UserAlreadyPlacedOrder.is_order_line_refunded(
             refund_line.order_line), is_refunded)
Пример #6
0
def prepare_basket(request, products, voucher=None):
    """
    Create or get the basket, add products, apply a voucher, and record referral data.

    Existing baskets are merged. Specified products will
    be added to the remaining open basket. If voucher is passed, all existing
    vouchers added to the basket are removed because we allow only one voucher per basket.
    Vouchers are not applied if an enrollment code product is in the basket.

    Arguments:
        request (Request): The request object made to the view.
        products (List): List of products to be added to the basket.
        voucher (Voucher): Voucher to apply to the basket.

    Returns:
        basket (Basket): Contains the product to be redeemed and the Voucher applied.
    """
    basket = Basket.get_basket(request.user, request.site)
    basket.flush()
    basket.save()
    basket_addition = get_class('basket.signals', 'basket_addition')
    already_purchased_products = []
    for product in products:
        if product.is_enrollment_code_product or \
                not UserAlreadyPlacedOrder.user_already_placed_order(request.user, product):
            basket.add_product(product, 1)
            # Call signal handler to notify listeners that something has been added to the basket
            basket_addition.send(sender=basket_addition,
                                 product=product,
                                 user=request.user,
                                 request=request,
                                 basket=basket)
        else:
            already_purchased_products.append(product)
            logger.warning(
                'User [%s] attempted to repurchase the [%s] seat of course [%s]',
                request.user.username, mode_for_seat(product),
                product.course_id)
    if already_purchased_products and basket.is_empty:
        raise AlreadyPlacedOrderException

    if len(products) == 1 and products[0].is_enrollment_code_product:
        basket.clear_vouchers()
    elif voucher:
        basket.clear_vouchers()
        basket.vouchers.add(voucher)
        Applicator().apply(basket, request.user, request)
        logger.info('Applied Voucher [%s] to basket [%s].', voucher.code,
                    basket.id)

    attribute_cookie_data(basket, request)
    return basket
Пример #7
0
 def test_already_have_refunded_order(self):
     """
     Test the case that user have a refunded order for the product.
     """
     user = self.create_user()
     refund = RefundFactory(user=user)
     refund_line = RefundLine.objects.get(refund=refund)
     refund_line.status = 'Complete'
     refund_line.save()
     product = self.get_order_product(order=refund.order)
     self.assertFalse(
         UserAlreadyPlacedOrder.user_already_placed_order(user=user,
                                                          product=product))
Пример #8
0
    def test_refunded_entitlement_order_connection_timeout(self):
        """
        Test the case that we get an error trying to get the entitlement from LMS
        """
        httpretty.register_uri(httpretty.GET,
                               get_lms_entitlement_api_url() +
                               'entitlements/' + self.course_entitlement_uuid +
                               '/',
                               status=200,
                               body={},
                               content_type='application/json',
                               side_effect=Timeout)

        self.assertFalse(
            UserAlreadyPlacedOrder.user_already_placed_order(
                user=self.user,
                product=self.course_entitlement,
                site=self.site))
Пример #9
0
def prepare_basket(request, products, voucher=None):
    """
    Create or get the basket, add products, apply a voucher, and record referral data.

    Existing baskets are merged. Specified products will
    be added to the remaining open basket. If voucher is passed, all existing
    vouchers added to the basket are removed because we allow only one voucher per basket.
    Vouchers are not applied if an enrollment code product is in the basket.

    Arguments:
        request (Request): The request object made to the view.
        products (List): List of products to be added to the basket.
        voucher (Voucher): Voucher to apply to the basket.

    Returns:
        basket (Basket): Contains the product to be redeemed and the Voucher applied.
    """
    basket = Basket.get_basket(request.user, request.site, request=request)
    basket_add_enterprise_catalog_attribute(basket, request.GET)
    basket.flush()
    basket.save()
    basket_addition = get_class('basket.signals', 'basket_addition')
    already_purchased_products = []
    bundle = request.GET.get('bundle')

    _set_basket_bundle_status(bundle, basket)

    if request.site.siteconfiguration.enable_embargo_check:
        if not embargo_check(request.user, request.site, products):
            messages.error(
                request,
                _('Due to export controls, we cannot allow you to access this course at this time.'
                  ))
            logger.warning(
                'User [%s] blocked by embargo check, not adding products to basket',
                request.user.username)
            return basket

    is_multi_product_basket = len(products) > 1
    for product in products:
        if product.is_enrollment_code_product or \
                not UserAlreadyPlacedOrder.user_already_placed_order(user=request.user,
                                                                     product=product, site=request.site):
            basket.add_product(product, 1)
            # Call signal handler to notify listeners that something has been added to the basket
            basket_addition.send(
                sender=basket_addition,
                product=product,
                user=request.user,
                request=request,
                basket=basket,
                is_multi_product_basket=is_multi_product_basket)
        else:
            already_purchased_products.append(product)
            logger.warning(
                'User [%s] attempted to repurchase the [%s] seat of course [%s]',
                request.user.username, mode_for_product(product),
                product.course_id)
    if already_purchased_products and basket.is_empty:
        raise AlreadyPlacedOrderException

    if len(products) == 1 and products[0].is_enrollment_code_product:
        basket.clear_vouchers()
    elif voucher or basket.vouchers.exists():
        voucher = voucher or basket.vouchers.first()
        basket.clear_vouchers()
        is_valid, message = validate_voucher(voucher, request.user, basket,
                                             request.site)
        if is_valid:
            apply_voucher_on_basket_and_check_discount(voucher, request,
                                                       basket)
        else:
            logger.warning(
                '[Code Redemption Failure] The voucher is not valid for this basket. '
                'User: %s, Basket: %s, Code: %s, Message: %s',
                request.user.username, request.basket.id, voucher.code,
                message)
    logger.info(
        '----------------------Baket Currency------------------------ %s',
        basket.currency)
    attribute_cookie_data(basket, request)
    return basket
Пример #10
0
def prepare_basket(request, products, voucher=None):
    """
    Create or get the basket, add products, apply a voucher, and record referral data.

    Existing baskets are merged. Specified products will
    be added to the remaining open basket. If voucher is passed, all existing
    vouchers added to the basket are removed because we allow only one voucher per basket.
    Vouchers are not applied if an enrollment code product is in the basket.

    Arguments:
        request (Request): The request object made to the view.
        products (List): List of products to be added to the basket.
        voucher (Voucher): Voucher to apply to the basket.

    Returns:
        basket (Basket): Contains the product to be redeemed and the Voucher applied.
    """
    basket = Basket.get_basket(request.user, request.site)
    basket_add_enterprise_catalog_attribute(basket, request.GET)
    basket.flush()
    basket.save()
    basket_addition = get_class('basket.signals', 'basket_addition')
    already_purchased_products = []
    bundle = request.GET.get('bundle')

    _set_basket_bundle_status(bundle, basket)

    if request.site.siteconfiguration.enable_embargo_check:
        if not embargo_check(request.user, request.site, products):
            messages.error(
                request,
                _('Due to export controls, we cannot allow you to access this course at this time.'
                  ))
            logger.warning(
                'User [%s] blocked by embargo check, not adding products to basket',
                request.user.username)
            return basket

    is_multi_product_basket = len(products) > 1
    for product in products:
        # Multiple clicks can try adding twice, return if product is seat already in basket
        if is_duplicate_seat_attempt(basket, product):
            logger.info(
                'User [%s] repeated request to add [%s] seat of course [%s], will ignore',
                request.user.username, mode_for_product(product),
                product.course_id)
            return basket

        if product.is_enrollment_code_product or \
                not UserAlreadyPlacedOrder.user_already_placed_order(user=request.user,
                                                                     product=product, site=request.site):
            basket.add_product(product, 1)
            # Call signal handler to notify listeners that something has been added to the basket
            basket_addition.send(
                sender=basket_addition,
                product=product,
                user=request.user,
                request=request,
                basket=basket,
                is_multi_product_basket=is_multi_product_basket)
        else:
            already_purchased_products.append(product)
            logger.warning(
                'User [%s] attempted to repurchase the [%s] seat of course [%s]',
                request.user.username, mode_for_product(product),
                product.course_id)
    if already_purchased_products and basket.is_empty:
        raise AlreadyPlacedOrderException

    # Waiting to check and send segment event until after products are added into the basket
    # just in case the AlreadyPlacedOrderException is raised
    if bundle:
        program = get_program(bundle, request.site.siteconfiguration)
        bundle_properties = {
            'bundle_id': bundle,
            'cart_id': basket.id,
            'title': program.get('title'),
            'total_price': basket.total_excl_tax,
            'quantity': basket.lines.count(),
        }
        if program.get('type_attrs',
                       {}).get('slug') and program.get('marketing_slug'):
            bundle_properties['marketing_slug'] = program['type_attrs'][
                'slug'] + '/' + program.get('marketing_slug')
        track_segment_event(request.site, request.user,
                            'edx.bi.ecommerce.basket.bundle_added',
                            bundle_properties)

    if len(products) == 1 and products[0].is_enrollment_code_product:
        basket.clear_vouchers()
    elif voucher or basket.vouchers.exists():
        voucher = voucher or basket.vouchers.first()
        basket.clear_vouchers()
        is_valid, message = validate_voucher(voucher, request.user, basket,
                                             request.site)
        if is_valid:
            apply_voucher_on_basket_and_check_discount(voucher, request,
                                                       basket)
        else:
            logger.warning(
                '[Code Redemption Failure] The voucher is not valid for this basket. '
                'User: %s, Basket: %s, Code: %s, Message: %s',
                request.user.username, request.basket.id, voucher.code,
                message)

    attribute_cookie_data(basket, request)
    return basket
Пример #11
0
def prepare_basket(request, products, voucher=None):
    """
    Create or get the basket, add products, apply a voucher, and record referral data.

    Existing baskets are merged. Specified products will
    be added to the remaining open basket. If voucher is passed, all existing
    vouchers added to the basket are removed because we allow only one voucher per basket.
    Vouchers are not applied if an enrollment code product is in the basket.

    Arguments:
        request (Request): The request object made to the view.
        products (List): List of products to be added to the basket.
        voucher (Voucher): Voucher to apply to the basket.

    Returns:
        basket (Basket): Contains the product to be redeemed and the Voucher applied.
    """
    basket = Basket.get_basket(request.user, request.site)
    basket.flush()
    basket.save()
    basket_addition = get_class('basket.signals', 'basket_addition')
    already_purchased_products = []
    bundle = request.GET.get('bundle')

    if bundle:
        BasketAttribute.objects.update_or_create(
            basket=basket,
            attribute_type=BasketAttributeType.objects.get(name=BUNDLE),
            defaults={'value_text': bundle})
        basket.clear_vouchers()
    else:
        BasketAttribute.objects.filter(basket=basket,
                                       attribute_type__name=BUNDLE).delete()

    if request.site.siteconfiguration.enable_embargo_check:
        if not embargo_check(request.user, request.site, products):
            messages.error(
                request,
                _('Due to export controls, we cannot allow you to access this course at this time.'
                  ))
            logger.warning(
                'User [%s] blocked by embargo check, not adding products to basket',
                request.user.username)
            return basket

    is_multi_product_basket = True if len(products) > 1 else False
    for product in products:
        if product.is_enrollment_code_product or \
                not UserAlreadyPlacedOrder.user_already_placed_order(user=request.user,
                                                                     product=product, site=request.site):
            basket.add_product(product, 1)
            # Call signal handler to notify listeners that something has been added to the basket
            basket_addition.send(
                sender=basket_addition,
                product=product,
                user=request.user,
                request=request,
                basket=basket,
                is_multi_product_basket=is_multi_product_basket)
        else:
            already_purchased_products.append(product)
            logger.warning(
                'User [%s] attempted to repurchase the [%s] seat of course [%s]',
                request.user.username, mode_for_product(product),
                product.course_id)
    if already_purchased_products and basket.is_empty:
        raise AlreadyPlacedOrderException

    if len(products) == 1 and products[0].is_enrollment_code_product:
        basket.clear_vouchers()
    elif voucher:
        basket.clear_vouchers()
        basket.vouchers.add(voucher)
        Applicator().apply(basket, request.user, request)
        logger.info('Applied Voucher [%s] to basket [%s].', voucher.code,
                    basket.id)

    attribute_cookie_data(basket, request)
    return basket