Exemple #1
0
 def setUp(self):
     self.product = create_product(num_in_stock=10)
     self.user_basket = Basket()
     self.user_basket.strategy = strategy.Default()
     add_product(self.user_basket, product=self.product)
     self.cookie_basket = Basket()
     self.cookie_basket.strategy = strategy.Default()
     add_product(self.cookie_basket, quantity=2, product=self.product)
     self.user_basket.merge(self.cookie_basket, add_quantities=False)
Exemple #2
0
    def setUp(self):
        self.product = factories.create_product()
        self.record = factories.create_stockrecord(self.product,
                                                   price_excl_tax=D('10.00'))
        self.purchase_info = factories.create_purchase_info(self.record)

        self.main_basket = Basket()
        self.main_basket.strategy = strategy.Default()
        self.main_basket.add(self.product, quantity=2)

        self.merge_basket = Basket()
        self.merge_basket.strategy = strategy.Default()
        self.merge_basket.add(self.product, quantity=1)

        self.main_basket.merge(self.merge_basket)
Exemple #3
0
    def _get_basket(self, basket_id):
        if not basket_id:
            return None

        try:
            basket_id = int(basket_id)
            basket = Basket.objects.get(id=basket_id)
            basket.strategy = strategy.Default()

            # TODO: Remove as a part of REVMI-124 as this is a hacky solution
            # The problem is that orders are being created after payment processing, and the discount is not
            # saved in the database, so it needs to be calculated again in order to save the correct info to the
            # order. REVMI-124 will create the order before payment processing, when we have the discount context.
            self._add_dynamic_discount_to_request(basket)
            # End TODO

            Applicator().apply(basket, basket.owner, self.request)
            logger.info(
                'Applicator applied, basket id: [%s]',
                basket.id)
            return basket
        except (ValueError, ObjectDoesNotExist) as error:
            logger.warning(
                'Could not get basket--error: [%s]',
                str(error))
            return None
Exemple #4
0
    def test_total_excludes_unavailable_products_with_unknown_price(self):
        new_product = factories.create_product()
        factories.create_stockrecord(new_product, price_excl_tax=D('5.00'))
        self.basket.add(new_product, 1)

        class UnavailableProductStrategy(strategy.Default):
            """ A test strategy that makes a specific product unavailable """
            def availability_policy(self, product, stockrecord):
                if product == new_product:
                    return availability.Unavailable()
                return super(UnavailableProductStrategy,
                             self).availability_policy(product, stockrecord)

            def pricing_policy(self, product, stockrecord):
                if product == new_product:
                    return prices.Unavailable()
                return super(UnavailableProductStrategy,
                             self).pricing_policy(product, stockrecord)

        try:
            self.basket.strategy = UnavailableProductStrategy()
            self.assertEqual(
                self.basket.all_lines()[1].get_warning(),
                u"'D\xf9\uff4d\u03fb\u03d2 title' is no longer available")
            self.assertEqual(self.basket.total_excl_tax, 100)
        finally:
            self.basket.strategy = strategy.Default()
Exemple #5
0
def create_order(number=None, basket=None, user=None, shipping_address=None,
                 shipping_method=None, billing_address=None,
                 total=None, **kwargs):
    """
    Helper method for creating an order for testing
    """
    if not basket:
        basket = Basket.objects.create()
        basket.strategy = strategy.Default()
        product = create_product()
        create_stockrecord(
            product, num_in_stock=10, price_excl_tax=D('10.00'))
        basket.add_product(product)
    if not basket.id:
        basket.save()
    if shipping_method is None:
        shipping_method = Free()
    if total is None:
        total = OrderTotalCalculator().calculate(basket, shipping_method)
    order = OrderCreator().place_order(
        order_number=number,
        user=user,
        basket=basket,
        shipping_address=shipping_address,
        shipping_method=shipping_method,
        billing_address=billing_address,
        total=total,
        **kwargs)
    basket.set_as_submitted()
    return order
Exemple #6
0
    def _get_basket(self, payment_id):
        """
        Retrieve a basket using a payment ID.

        Arguments:
            payment_id: payment_id received from PayPal.

        Returns:
            It will return related basket or log exception and return None if
            duplicate payment_id received or any other exception occurred.

        """
        try:
            basket = PaymentProcessorResponse.objects.get(
                processor_name=self.payment_processor.NAME,
                transaction_id=payment_id).basket
            basket.strategy = strategy.Default()
            return basket
        except MultipleObjectsReturned:
            logger.exception(
                u"Duplicate payment ID [%s] received from PayPal.", payment_id)
            return None
        except Exception:  # pylint: disable=broad-except
            logger.exception(
                u"Unexpected error during basket retrieval while executing PayPal payment."
            )
            return None
Exemple #7
0
 def setUp(self):
     self.basket = Basket()
     self.basket.strategy = strategy.Default()
     self.product = factories.create_product()
     self.record = factories.create_stockrecord(self.product,
                                                price_excl_tax=D('10.00'))
     self.purchase_info = factories.create_purchase_info(self.record)
     self.basket.add(self.product, 10)
 def setUp(self):
     self.strategy = strategy.Default()
     parent = factories.create_product()
     factories.create_product(parent=parent, price=D('10.00'),
                              num_in_stock=0)
     for x in range(2):
         factories.create_product(parent=parent)
     self.info = self.strategy.fetch_for_group(parent)
Exemple #9
0
def create_basket(empty=False):
    basket = Basket.objects.create()
    basket.strategy = strategy.Default()
    if not empty:
        product = create_product()
        create_stockrecord(product)
        basket.add_product(product)
    return basket
 def setUp(self):
     self.basket = Basket()
     self.basket.strategy = strategy.Default()
     self.product = factories.create_product()
     self.record = factories.create_stockrecord(currency='GBP',
                                                product=self.product,
                                                price=D('10.00'))
     self.purchase_info = factories.create_purchase_info(self.record)
     self.basket.add(self.product)
Exemple #11
0
    def test_can_reorder_a_previous_order(self):
        order_history_page = self.app.get(
            reverse('customer:order', args=[self.order.number]), user=self.user)
        form = order_history_page.forms['order_form_%d' % self.order.id]
        form.submit()

        basket = Basket.open.get(owner=self.user)
        basket.strategy = strategy.Default()
        self.assertEqual(1, basket.all_lines().count())
    def test_line_tax_for_zero_tax_strategies(self):
        basket = Basket()
        basket.strategy = strategy.Default()
        product = factories.create_product()
        # Tax for the default strategy will be 0
        factories.create_stockrecord(
            product, price_excl_tax=D('75.00'), num_in_stock=10)
        basket.add(product, 1)

        self.assertEqual(basket.lines.first().line_tax, D('0'))
    def test_can_reorder_a_previous_order_line(self):
        order_history_page = self.app.get(reverse(
            'customer:order', kwargs={'order_number': self.order.number}),
                                          user=self.user)
        line = self.order.lines.all()[0]
        form = order_history_page.forms['line_form_%d' % line.id]
        form.submit()

        basket = Basket.open.get(owner=self.user)
        basket.strategy = strategy.Default()
        self.assertEqual(1, basket.all_lines().count())
    def test_totals_for_free_products(self):
        basket = Basket()
        basket.strategy = strategy.Default()
        # Add a zero-priced product to the basket
        product = factories.create_product()
        factories.create_stockrecord(product, price=D('0.00'), num_in_stock=10)
        basket.add(product, 1)

        self.assertEqual(basket.lines.count(), 1)
        self.assertEqual(basket.total_excl_tax, 0)
        self.assertEqual(basket.total_incl_tax, 0)
Exemple #15
0
    def _get_basket(self, payment_id):
        """
        Retrieve a basket using a payment ID.

        Arguments:
            payment_id: payment_id received from PayPal.

        Returns:
            It will return related basket or log exception and return None if
            duplicate payment_id received or any other exception occurred.

        """
        try:
            basket = PaymentProcessorResponse.objects.get(
                processor_name=self.payment_processor.NAME,
                transaction_id=payment_id).basket
            basket.strategy = strategy.Default()
            # TODO: Remove as a part of REVMI-124 as this is a hacky solution
            # The problem is that orders are being created after payment processing, and the discount is not
            # saved in the database, so it needs to be calculated again in order to save the correct info to the
            # order. REVMI-124 will create the order before payment processing, when we have the discount context.
            if waffle.flag_is_active(
                    self.request,
                    DYNAMIC_DISCOUNT_FLAG) and basket.lines.count() == 1:
                discount_lms_url = get_lms_url('/api/discounts/')
                lms_discount_client = EdxRestApiClient(
                    discount_lms_url,
                    jwt=self.request.site.siteconfiguration.access_token)
                ck = basket.lines.first().product.course_id
                user_id = self.request.user.lms_user_id
                try:
                    response = lms_discount_client.user(user_id).course(
                        ck).get()
                    self.request.GET = self.request.GET.copy()
                    self.request.GET['discount_jwt'] = response.get('jwt')
                except (SlumberHttpBaseException, Timeout) as error:
                    logger.warning(
                        'Failed to get discount jwt from LMS. [%s] returned [%s]',
                        discount_lms_url, error.response)
            # END TODO

            Applicator().apply(basket, basket.owner, self.request)

            basket_add_organization_attribute(basket, self.request.GET)
            return basket
        except MultipleObjectsReturned:
            logger.warning(u"Duplicate payment ID [%s] received from PayPal.",
                           payment_id)
            return None
        except Exception:  # pylint: disable=broad-except
            logger.exception(
                u"Unexpected error during basket retrieval while executing PayPal payment."
            )
            return None
Exemple #16
0
    def _get_basket(self, basket_id):
        if not basket_id:
            return None

        try:
            basket_id = int(basket_id)
            basket = Basket.objects.get(id=basket_id)
            basket.strategy = strategy.Default()
            return basket
        except (ValueError, ObjectDoesNotExist):
            return None
Exemple #17
0
    def _get_basket(self, basket_id):
        if not basket_id:
            return None

        try:
            basket_id = int(basket_id)
            basket = Basket.objects.get(id=basket_id)
            basket.strategy = strategy.Default()
            Applicator().apply(basket, basket.owner, self.request)
            return basket
        except (ValueError, ObjectDoesNotExist):
            return None
Exemple #18
0
    def _get_basket(self, basket_id):
        if not basket_id:
            return None

        try:
            basket_id = int(basket_id)
            basket = Basket.objects.get(id=basket_id)
            basket.strategy = strategy.Default()
            # TODO: Remove as a part of REVMI-124 as this is a hacky solution
            # The problem is that orders are being created after payment processing, and the discount is not
            # saved in the database, so it needs to be calculated again in order to save the correct info to the
            # order. REVMI-124 will create the order before payment processing, when we have the discount context.
            if waffle.flag_is_active(self.request, DYNAMIC_DISCOUNT_FLAG) and basket.lines.count() == 1:  # pragma: no cover  pylint: disable=line-too-long
                discount_lms_url = get_lms_url('/api/discounts/')
                lms_discount_client = EdxRestApiClient(
                    discount_lms_url,
                    jwt=self.request.site.siteconfiguration.access_token)
                ck = basket.lines.first().product.course_id
                user_id = basket.owner.lms_user_id
                try:
                    response = lms_discount_client.user(user_id).course(
                        ck).get()
                    self.request.POST = self.request.POST.copy()
                    self.request.POST['discount_jwt'] = response.get('jwt')
                    logger.info(
                        """Received discount jwt from LMS with
                        url: [%s],
                        user_id: [%s],
                        course_id: [%s],
                        and basket_id: [%s]
                        returned [%s]""", discount_lms_url, str(user_id), ck,
                        basket.id, response)
                except (SlumberHttpBaseException,
                        requests.exceptions.Timeout) as error:
                    logger.warning(
                        """Failed to receive discount jwt from LMS with
                        url: [%s],
                        user_id: [%s],
                        course_id: [%s],
                        and basket_id: [%s]
                        returned [%s]""", discount_lms_url, str(user_id), ck,
                        basket.id,
                        vars(error.response)
                        if hasattr(error, 'response') else '')
            # End TODO
            Applicator().apply(basket, basket.owner, self.request)
            logger.info('Applicator applied, basket id: [%s]', basket.id)
            return basket
        except (ValueError, ObjectDoesNotExist) as error:
            logger.warning('Could not get basket--error: [%s]', str(error))
            return None
Exemple #19
0
def add_product(basket, price=None, quantity=1, product=None):
    """
    Helper to add a product to the basket.
    """
    if not hasattr(basket, 'strategy'):
        basket.strategy = strategy.Default()
    if price is None:
        price = D('1')
    if product and product.has_stockrecords:
        record = product.stockrecords.all()[0]
    else:
        record = factories.create_stockrecord(product=product,
                                              price_excl_tax=price,
                                              num_in_stock=quantity + 1)
    basket.add_product(record.product, quantity)
Exemple #20
0
    def _get_basket(self, basket_id):
        if not basket_id:
            return None

        try:
            basket_id = int(basket_id)
            basket = Basket.objects.get(id=basket_id)
            basket.strategy = strategy.Default()

            Applicator().apply(basket, basket.owner, self.request)
            logger.info('Applicator applied, basket id: [%s]', basket.id)
            return basket
        except (ValueError, ObjectDoesNotExist) as error:
            logger.warning('Could not get basket--error: [%s]', str(error))
            return None
Exemple #21
0
    def get_basket(self, basket_id):
        """
            Retrieve a basket using a basket Id.

            Arguments:
                payment_id: payment_id received from AuthorizeNet.
            Returns:
                It will return related basket
        """
        if not basket_id:
            return None

        try:
            basket = Basket.objects.get(id=basket_id)
            basket.strategy = strategy.Default()
            return basket
        except (ValueError, ObjectDoesNotExist):
            return None
Exemple #22
0
    def test_basket_lines_are_converted_to_xml(self):
        product = factories.create_product(price=D('12.99'))
        basket = Basket()

        # Nasty hack to make test suite work with both Oscar 0.5 and 0.6
        try:
            from oscar.apps.partner import strategy
        except ImportError:
            pass
        else:
            basket.strategy = strategy.Default()

        basket.add_product(product)
        data = the3rdman.build_data_dict(basket=basket)
        doc = the3rdman.add_fraud_fields(**data)
        xml = doc.toxml()
        self.assertXmlElementEquals(
            xml, '3', 'The3rdMan.CustomerInformation.sales_channel')
Exemple #23
0
    def test_cannot_reorder_line_when_basket_maximum_exceeded(self):
        order = create_order(user=self.user)
        line = order.lines.all()[0]

        product = create_product(price=D('12.00'))
        product_page = self.get(line.product.get_absolute_url())
        product_page.forms['add_to_basket_form'].submit()

        basket = Basket.objects.all()[0]
        basket.strategy = strategy.Default()
        self.assertEqual(len(basket.all_lines()), 1)

        # Try to reorder a line
        order_page = self.get(reverse('customer:order', args=(order.number,)))
        order_page.forms['line_form_%s' % line.id].submit()

        self.assertEqual(len(basket.all_lines()), 1)
        self.assertNotEqual(line.product.pk, product.pk)
Exemple #24
0
def refund_basket_transactions(site, basket_ids):
    baskets = Basket.objects.filter(site=site, id__in=basket_ids)

    success_count = 0
    failure_count = 0

    for basket in baskets:
        basket.strategy = strategy.Default()
        Applicator().apply(basket, basket.owner, None)

        logger.info('Refunding transactions for basket [%d]...', basket.id)
        transactions = set(
            list(
                basket.paymentprocessorresponse_set.values_list(
                    'processor_name', 'transaction_id')))

        for processor_name, transaction_id in transactions:
            try:
                logger.info(
                    'Issuing credit for [%s] transaction [%s] made against basket [%d]...',
                    processor_name, transaction_id, basket.id)
                payment_processor = _get_payment_processor(
                    site, processor_name)
                payment_processor.issue_credit(basket.order_number, basket,
                                               transaction_id,
                                               basket.total_excl_tax,
                                               basket.currency)
                success_count += 1
                logger.info(
                    'Successfully issued credit for [%s] transaction [%s] made against basket [%d].',
                    processor_name, transaction_id, basket.id)
            except Exception:  # pylint: disable=broad-except
                failure_count += 1
                logger.exception(
                    'Failed to issue credit for [%s] transaction [%s] made against basket [%d].',
                    processor_name, transaction_id, basket.id)
        logger.info('Finished processing refunds for basket [%d].', basket.id)

    msg = 'Finished refunding basket transactions. [{success_count}] transactions were successfully refunded. ' \
          '[{failure_count}] attempts failed.'.format(success_count=success_count, failure_count=failure_count)
    logger.info(msg)

    return success_count, failure_count
    def test_cannot_reorder_line_when_basket_maximum_exceeded(self):
        order = create_order(user=self.user)
        line = order.lines.all()[0]

        # add a product
        product = create_product(price=D('12.00'))
        self.client.post(reverse('basket:add'), {
            'product_id': product.id,
            'quantity': 1
        })

        basket = Basket.objects.all()[0]
        basket.strategy = strategy.Default()
        self.assertEquals(len(basket.all_lines()), 1)

        self.client.post(
            reverse('customer:order-line', args=(order.number, line.pk)),
            {'action': 'reorder'})

        self.assertEquals(len(basket.all_lines()), 1)
        self.assertNotEqual(line.product.pk, product.pk)
Exemple #26
0
    def _get_basket(self, payment_id):
        """
        Retrieve a basket using a payment ID.

        Arguments:
            payment_id: payment_id received from PayPal.

        Returns:
            It will return related basket or log exception and return None if
            duplicate payment_id received or any other exception occurred.

        """
        try:
            basket = PaymentProcessorResponse.objects.get(
                processor_name=self.payment_processor.NAME,
                transaction_id=payment_id).basket
            basket.strategy = strategy.Default()

            # TODO: Remove as a part of REVMI-124 as this is a hacky solution
            # The problem is that orders are being created after payment processing, and the discount is not
            # saved in the database, so it needs to be calculated again in order to save the correct info to the
            # order. REVMI-124 will create the order before payment processing, when we have the discount context.
            self._add_dynamic_discount_to_request(basket)
            # END TODO

            Applicator().apply(basket, basket.owner, self.request)

            basket_add_organization_attribute(basket, self.request.GET)
            return basket
        except MultipleObjectsReturned:
            logger.warning(u"Duplicate payment ID [%s] received from PayPal.",
                           payment_id)
            return None
        except Exception:  # pylint: disable=broad-except
            logger.exception(
                u"Unexpected error during basket retrieval while executing PayPal payment."
            )
            return None
Exemple #27
0
    def get(self, request, ppr_id):
        ppr = get_object_or_404(PaymentProcessorResponse, id=ppr_id)
        basket = ppr.basket
        basket.strategy = strategy.Default()

        # What follows is basically a copy-paste from paypal's GET view handler
        receipt_url = get_receipt_page_url(
            order_number=basket.order_number,
            site_configuration=basket.site.siteconfiguration,
            disable_back_button=True,
        )

        try:
            with transaction.atomic():
                try:
                    self.handle_payment(ppr.transaction_id, basket)
                except PaymentError:
                    return redirect(self.payment_processor.error_url)
        except PaymentError:
            return redirect(self.payment_processor.error_url)
        except:  # pylint: disable=bare-except
            logger.exception(
                "Attempts to handle payment for basket [%d] failed.",
                basket.id)
            return redirect(receipt_url)

        try:
            order = self.create_order(request, basket)
        except Exception:  # pylint: disable=broad-except
            return redirect(receipt_url)

        try:
            self.handle_post_order(order)
        except Exception:  # pylint: disable=broad-except
            self.log_order_placement_exception(basket.order_number, basket.id)

        return redirect(receipt_url)
Exemple #28
0
    def _get_basket(self, payment_id):
        """
        Retrieve a basket using a payment ID.

        Arguments:
            payment_id: payment_id received from Alipay.

        Returns:

        """
        try:
            basket = PaymentProcessorResponse.objects.get(
                processor_name=self.payment_processor.NAME,
                transaction_id=payment_id).basket
            basket.strategy = strategy.Default()
            Applicator().apply(basket, basket.owner, self.request)

            basket_add_organization_attribute(basket, self.request.GET)
            return basket
        except MultipleObjectsReturned:
            return None
        except Exception, e:
            logger.exception(e)
            return None
Exemple #29
0
 def setUp(self):
     self.basket = Basket()
     self.basket.strategy = strategy.Default()
 def setUp(self):
     self.strategy = strategy.Default()
     parent = factories.create_product()
     for x in range(3):
         factories.create_product(parent=parent)
     self.info = self.strategy.fetch_for_group(parent)