Beispiel #1
0
 def test_create_line_reference(self):
     basket = BasketFactory()
     product = ProductFactory(title="A product")
     option = OptionFactory(name="product_option", code="product_option")
     option_product = ProductFactory(title=u'Asunción')
     options = [{'option': option, 'value': option_product}]
     basket.add_product(product, options=options)
Beispiel #2
0
def filled_basket():
    basket = BasketFactory()
    product1 = ProductFactory()
    product2 = ProductFactory()
    basket.add_product(product1, quantity=10)
    basket.add_product(product2, quantity=20)
    return basket
Beispiel #3
0
def prepare_voucher(code='COUPONTEST',
                    _range=None,
                    start_datetime=None,
                    end_datetime=None,
                    benefit_value=100,
                    benefit_type=Benefit.PERCENTAGE,
                    usage=Voucher.SINGLE_USE,
                    max_usage=None,
                    email_domains=None,
                    enterprise_customer=None,
                    site=None):
    """ Helper function to create a voucher and add an offer to it that contains a product. """

    # NOTE (CCB): We use empty categories here to avoid unique-constraint issues that occur when we use
    # ProductCategoryFactory in conjunction with pre-created Category objects.
    if _range is None:
        product = ProductFactory(categories=[])
        _range = RangeFactory(products=[product],
                              enterprise_customer=enterprise_customer)
    elif _range.num_products() > 0:
        product = _range.all_products()[0]
    else:
        product = ProductFactory(categories=[])

    if start_datetime is None:
        start_datetime = now() - timedelta(days=1)

    if end_datetime is None:
        end_datetime = now() + timedelta(days=10)

    voucher = VoucherFactory(code=code,
                             start_datetime=start_datetime,
                             end_datetime=end_datetime,
                             usage=usage)
    benefit = BenefitFactory(type=benefit_type,
                             range=_range,
                             value=benefit_value)
    condition = ConditionFactory(value=1,
                                 range=_range,
                                 enterprise_customer_uuid=enterprise_customer)
    if max_usage:
        offer = ConditionalOfferFactory(offer_type=ConditionalOffer.VOUCHER,
                                        benefit=benefit,
                                        condition=condition,
                                        max_global_applications=max_usage,
                                        email_domains=email_domains,
                                        priority=OFFER_PRIORITY_VOUCHER)
    else:
        offer = ConditionalOfferFactory(
            offer_type=ConditionalOffer.VOUCHER,
            benefit=benefit,
            condition=condition,
            email_domains=email_domains,
            partner=site.siteconfiguration.partner if site else None,
            priority=OFFER_PRIORITY_VOUCHER)
    voucher.offers.add(offer)
    return voucher, product
Beispiel #4
0
 def test_basket_lines_queryset_is_ordered(self):
     # This is needed to make sure a formset is not performing the query
     # again with an order_by clause (losing all calculated discounts)
     basket = BasketFactory()
     product = ProductFactory(title="A product")
     another_product = ProductFactory(title="Another product")
     basket.add_product(product)
     basket.add_product(another_product)
     queryset = basket.all_lines()
     self.assertTrue(queryset.ordered)
Beispiel #5
0
    def test_is_duplicate_seat_attempt__seats(self):
        """ Verify we get a correct response for duplicate seat check (seats) """
        product_type_seat = ProductClass.objects.create(name='Seat')
        product1 = ProductFactory(stockrecords__partner__short_code='test1', product_class=product_type_seat)
        product2 = ProductFactory(stockrecords__partner__short_code='test2', product_class=product_type_seat)
        seat_basket = prepare_basket(self.request, [product1])
        result_product1 = is_duplicate_seat_attempt(seat_basket, product1)
        result_product2 = is_duplicate_seat_attempt(seat_basket, product2)

        self.assertTrue(result_product1)
        self.assertFalse(result_product2)
Beispiel #6
0
 def test_prepare_basket_with_multiple_products(self):
     """ Verify a basket is returned and only contains a single product. """
     product1 = ProductFactory(stockrecords__partner__short_code='test1')
     product2 = ProductFactory(stockrecords__partner__short_code='test2')
     prepare_basket(self.request, [product1])
     basket = prepare_basket(self.request, [product2])
     self.assertIsNotNone(basket)
     self.assertEqual(basket.status, Basket.OPEN)
     self.assertEqual(basket.lines.count(), 1)
     self.assertEqual(basket.lines.first().product, product2)
     self.assertEqual(basket.product_quantity(product2), 1)
Beispiel #7
0
    def test_wishlists_containing_product(self):
        p1 = ProductFactory()
        p2 = ProductFactory()
        user = UserFactory()
        wishlist1 = WishListFactory(owner=user)
        WishListFactory(owner=user)
        wishlist1.add(p1)

        containing_one = wishlists_containing_product(Wishlist.objects.all(),
                                                      p1)
        self.assertEqual(len(containing_one), 1)
        self.assertEqual(containing_one[0], wishlist1)
        containing_none = wishlists_containing_product(Wishlist.objects.all(),
                                                       p2)
        self.assertEqual(len(containing_none), 0)
Beispiel #8
0
    def test_description(self):
        basket = BasketFactory()
        product = ProductFactory(title="A product")
        basket.add_product(product)

        line = basket.lines.first()
        self.assertEqual(line.description, "A product")
Beispiel #9
0
    def test_non_free_basket_order(self, __):
        """ Verify an error is raised for non-free basket. """
        basket = create_basket(empty=True)
        basket.add_product(ProductFactory(stockrecords__price_excl_tax=10))

        with self.assertRaises(BasketNotFreeError):
            EdxOrderPlacementMixin().place_free_order(basket)
Beispiel #10
0
    def test_prepare_basket_with_enterprise_catalog(self):
        """
        Test `prepare_basket` with enterprise catalog.
        """
        product = ProductFactory()
        request = self.request
        expected_enterprise_catalog_uuid = str(uuid4())
        request.GET = {'catalog': expected_enterprise_catalog_uuid}
        basket = prepare_basket(request, [product])

        # Verify that the enterprise catalog attribute exists for the basket
        # when basket is prepared with the value of provide catalog UUID
        enterprise_catalog_uuid = BasketAttribute.objects.get(
            basket=basket,
            attribute_type__name=ENTERPRISE_CATALOG_ATTRIBUTE_TYPE).value_text
        assert expected_enterprise_catalog_uuid == enterprise_catalog_uuid

        # Now verify that `prepare_basket` method removes the enterprise
        # catalog attribute if there is no `catalog` query parameter in url
        request.GET = {}
        basket = prepare_basket(request, [product])

        # Verify that enterprise catalog attribute does not exists for a basket
        # when basket is prepared with the value of provided catalog UUID
        with self.assertRaises(BasketAttribute.DoesNotExist):
            BasketAttribute.objects.get(
                basket=basket,
                attribute_type__name=ENTERPRISE_CATALOG_ATTRIBUTE_TYPE)
Beispiel #11
0
    def test_prepare_basket_applies_valid_voucher_argument(self):
        """
            Tests that prepare_basket applies a valid voucher passed as an
            an argument, even when there is also a valid voucher already on
            the basket.
        """
        product = ProductFactory(stockrecords__partner__short_code='test1',
                                 stockrecords__price_excl_tax=100)
        new_range = RangeFactory(products=[product])
        new_voucher, __ = prepare_voucher(code='xyz',
                                          _range=new_range,
                                          benefit_value=10)
        existing_voucher, __ = prepare_voucher(code='test',
                                               _range=new_range,
                                               benefit_value=50)

        basket = BasketFactory(owner=self.request.user, site=self.request.site)
        basket.vouchers.add(existing_voucher)
        self.assertEqual(basket.vouchers.count(), 1)

        basket = prepare_basket(self.request, [product], new_voucher)
        self.assertIsNotNone(basket)
        self.assertEqual(basket.vouchers.count(), 1)
        self.assertEqual(basket.vouchers.first().code, 'XYZ')
        self.assertEqual(basket.total_discount, 10.00)
Beispiel #12
0
    def test_prepare_basket_affiliate_cookie_lifecycle(self):
        """ Verify a basket is returned and referral captured. """
        product = ProductFactory()
        affiliate_id = 'test_affiliate'
        self.request.COOKIES['affiliate_id'] = affiliate_id
        basket = prepare_basket(self.request, product)

        # test affiliate id from cookie saved in referral
        referral = Referral.objects.get(basket_id=basket.id)
        self.assertEqual(referral.affiliate_id, affiliate_id)

        # update cookie
        new_affiliate_id = 'new_affiliate'
        self.request.COOKIES['affiliate_id'] = new_affiliate_id
        basket = prepare_basket(self.request, product)

        # test new affiliate id saved
        referral = Referral.objects.get(basket_id=basket.id)
        self.assertEqual(referral.affiliate_id, new_affiliate_id)

        # expire cookie
        del self.request.COOKIES['affiliate_id']
        basket = prepare_basket(self.request, product)

        # test referral record is deleted when no cookie set
        with self.assertRaises(Referral.DoesNotExist):
            Referral.objects.get(basket_id=basket.id)
Beispiel #13
0
    def test_attribution_atomic_transaction(self):
        """
        Verify that an IntegrityError raised while creating a referral
        does not prevent a basket from being created.
        """
        self._setup_request_cookie()
        product = ProductFactory()
        existing_basket = Basket.get_basket(self.request.user,
                                            self.request.site)
        existing_referral = Referral(basket=existing_basket,
                                     site=self.request.site)
        # Let's save an existing referral object to force the duplication happen in database
        existing_referral.save()

        with transaction.atomic():
            with mock.patch(
                    'ecommerce.extensions.basket.utils._referral_from_basket_site'
            ) as mock_get_referral:
                # Mock to return a duplicated referral object, so when saved, a DB integrity error is raised
                # Mocking with side_effect to raise IntegrityError will not roll back the DB transaction
                # We actually would handle the exception in the attribute_cookie_data method.
                # Only causing the true database conflict like what we are doing here, would cause the roll back
                mock_get_referral.return_value = Referral(
                    basket=existing_basket, site=self.request.site)
                basket = prepare_basket(self.request, [product])
                referral = Referral.objects.filter(basket=basket)

        self.assertEqual(len(referral), 1)
        self.assertIsNotNone(basket)
        self.assertTrue(basket.id > 0)
        self.assertEqual(basket.status, Basket.OPEN)
        self.assertEqual(basket.lines.count(), 1)
        self.assertEqual(basket.lines.first().product, product)
Beispiel #14
0
    def test_success(self):
        product_price = 100
        percentage_discount = 10
        product = ProductFactory(stockrecords__price_excl_tax=product_price)
        voucher, product = prepare_voucher(
            _range=RangeFactory(products=[product]),
            benefit_value=percentage_discount)
        self.request.user = UserFactory()
        basket = prepare_basket(self.request, [product], voucher)

        ppr = PaymentProcessorResponse.objects.create(basket=basket,
                                                      transaction_id='abc',
                                                      processor_name='paypal')
        with mock.patch.object(Paypal, 'issue_credit') as mock_issue_credit:
            mock_issue_credit.return_value = None

            assert refund_basket_transactions(self.site, [basket.id]) == (
                1,
                0,
            )
            total = product_price * (100 - percentage_discount) / 100.
            mock_issue_credit.assert_called_once_with(basket.order_number,
                                                      basket,
                                                      ppr.transaction_id,
                                                      total, basket.currency)
Beispiel #15
0
    def test_prepare_basket_with_bundle_voucher(self):
        """
        Test prepare_basket clears vouchers for a bundle
        """
        product = ProductFactory(stockrecords__price_excl_tax=100)
        new_range = RangeFactory(products=[
            product,
        ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)

        request = self.request
        basket = prepare_basket(request, [product], voucher)
        self.assertTrue(basket.vouchers.all())
        request.GET = {'bundle': TEST_BUNDLE_ID}
        program_data = {
            'marketing_slug': 'program-slug',
            'title': 'program title',
            'type_attrs': {
                'slug': 'micromasters'
            }
        }
        with mock.patch('ecommerce.extensions.basket.utils.get_program',
                        return_value=program_data):
            basket = prepare_basket(request, [product])
        self.assertFalse(basket.vouchers.all())
Beispiel #16
0
 def test_prepare_basket_raises_exception_for_purchased_product(self):
     """
     Test prepare_basket raises AlreadyPlacedOrderException if the product is already purchased by user
     """
     product = ProductFactory()
     with mock.patch.object(UserAlreadyPlacedOrder, 'user_already_placed_order', return_value=True):
         with self.assertRaises(AlreadyPlacedOrderException):
             prepare_basket(self.request, [product])
Beispiel #17
0
    def test_is_duplicate_seat_attempt__enrollment_code(self):
        """ Verify we get a correct response for duplicate seat check (false for Enrollment code)"""
        enrollment_class = ProductClass.objects.create(name='Enrollment Code')
        enrollment_product = ProductFactory(stockrecords__partner__short_code='test3', product_class=enrollment_class)
        basket_with_enrollment_code = prepare_basket(self.request, [enrollment_product])
        result_product3 = is_duplicate_seat_attempt(basket_with_enrollment_code, enrollment_product)

        self.assertFalse(result_product3)
Beispiel #18
0
    def test_place_free_order(self, __):
        """ Verify an order is placed and the basket is submitted. """
        basket = create_basket(empty=True)
        basket.add_product(ProductFactory(stockrecords__price_excl_tax=0))
        order = EdxOrderPlacementMixin().place_free_order(basket)

        self.assertIsNotNone(order)
        self.assertEqual(basket.status, Basket.SUBMITTED)
Beispiel #19
0
 def test_prepare_basket_calls_attribution_method(self):
     """ Verify a basket is returned and referral method called. """
     with mock.patch(
             'ecommerce.extensions.basket.utils.attribute_cookie_data'
     ) as mock_attr_method:
         product = ProductFactory()
         basket = prepare_basket(self.request, [product])
         mock_attr_method.assert_called_with(basket, self.request)
Beispiel #20
0
 def test_prepare_basket_with_duplicate_seat(self):
     """ Verify a basket fixes the case where flush doesn't work and we attempt adding duplicate seat. """
     with mock.patch('ecommerce.extensions.basket.utils.Basket.flush'):
         product_type_seat = ProductClass.objects.create(name='Seat')
         product1 = ProductFactory(stockrecords__partner__short_code='test1', product_class=product_type_seat)
         prepare_basket(self.request, [product1])
         basket = prepare_basket(self.request, [product1])  # try to add a duplicate seat
         self.assertEqual(basket.product_quantity(product1), 1)
Beispiel #21
0
    def test_available_with_offer(self):
        basket = BasketFactory()
        product1 = ProductFactory()
        product2 = ProductFactory()
        basket.add_product(product1, quantity=1)
        basket.add_product(product2, quantity=10)

        benefit = models.Benefit(
            type=models.Benefit.PERCENTAGE,
            value=10,
            max_affected_items=5,
        )
        benefit.save()

        offer1 = ConditionalOfferFactory(name='offer1', benefit=benefit)
        lines = basket.all_lines()
        assert lines[0].consumer.available(offer1) == 1
        assert lines[1].consumer.available(offer1) == 5
 def setUp(self):
     super(JournalProductUpdateSerializerTest, self).setUp()
     product_class = ProductClassFactory(name="Journal")
     self.product = ProductFactory(product_class=product_class,
                                   stockrecords=[],
                                   categories="")
     StockRecordFactory(partner_sku="unit02",
                        product=self.product,
                        partner=PartnerFactory(short_code="dummy-partner"))
    def test_description_with_attributes(self):
        basket = BasketFactory()
        product = ProductFactory(title="A product")
        basket.add_product(product)

        line = basket.lines.first()
        BasketLineAttributeFactory(
            line=line, value='\u2603', option__name='with')
        self.assertEqual(line.description, "A product (with = '\u2603')")
Beispiel #24
0
 def create_vouchers(self, partner=None, count=1):
     """Helper function that creates vouchers with a mocked coupon relation."""
     vouchers = VoucherFactory.create_batch(count)
     partner = partner or self.partner
     coupon_vouchers = CouponVouchers.objects.create(coupon=ProductFactory(
         stockrecords__partner=partner))
     for voucher in vouchers:
         voucher.offers.add(ConditionalOfferFactory())
         coupon_vouchers.vouchers.add(voucher)
     return vouchers
Beispiel #25
0
 def setUp(self):
     super(StockRecordSerializerForUpdateTest, self).setUp()
     self.stock_record = StockRecordFactory(
         partner=PartnerFactory(
             short_code="dummy-partner"
         ),
         product=ProductFactory(
             categories=""
         )
     )
Beispiel #26
0
 def test_prepare_basket_without_voucher(self):
     """ Verify a basket is returned and does not contain a voucher. """
     product = ProductFactory()
     basket = prepare_basket(self.request, [product])
     self.assertIsNotNone(basket)
     self.assertEqual(basket.status, Basket.OPEN)
     self.assertEqual(basket.lines.count(), 1)
     self.assertEqual(basket.lines.first().product, product)
     self.assertFalse(basket.vouchers.all())
     self.assertFalse(basket.applied_offers())
Beispiel #27
0
    def test_prepare_basket_attribute_delete(self):
        """
        Test prepare_basket removes the bundle attribute for a basket when a user is purchasing a single course
        """
        product = ProductFactory(categories=[],
                                 stockrecords__partner__short_code='second')
        request = self.request
        request.GET = {'bundle': TEST_BUNDLE_ID}
        program_data = {
            'marketing_slug': 'program-slug',
            'title': 'program title',
            'type_attrs': {
                'slug': 'micromasters'
            }
        }
        with mock.patch('ecommerce.extensions.basket.utils.get_program',
                        return_value=program_data):
            basket = prepare_basket(request, [product])

        # Verify that the bundle attribute exists for the basket when bundle is added to basket
        bundle_id = BasketAttribute.objects.get(
            basket=basket, attribute_type__name=BUNDLE).value_text
        self.assertEqual(bundle_id, TEST_BUNDLE_ID)

        # Verify that the attribute is deleted when a non-bundle product is added to the basket
        request.GET = {}
        with mock.patch(
                'ecommerce.extensions.basket.models.track_segment_event'
        ) as mock_track:
            with mock.patch('ecommerce.extensions.basket.models.get_program',
                            return_value=program_data):
                prepare_basket(request, [product])
            properties = {
                'bundle_id':
                TEST_BUNDLE_ID,
                'marketing_slug':
                program_data['type_attrs']['slug'] + '/' +
                program_data['marketing_slug'],
                'title':
                program_data['title'],
                'total_price':
                basket.total_excl_tax,
                'quantity':
                basket.lines.count(),
            }
            mock_track.assert_any_call(
                request.site, request.user,
                'edx.bi.ecommerce.basket.bundle_removed', properties)
        with self.assertRaises(BasketAttribute.DoesNotExist):
            BasketAttribute.objects.get(basket=basket,
                                        attribute_type__name=BUNDLE)

        # Verify that no exception is raised when no basket attribute exists fitting the delete statement parameters
        prepare_basket(request, [product])
Beispiel #28
0
 def test_prepare_basket_with_bundle_voucher(self):
     """
     Test prepare_basket clears vouchers for a bundle
     """
     product = ProductFactory()
     voucher = VoucherFactory(code='FIRST')
     request = self.request
     basket = prepare_basket(request, [product], voucher)
     self.assertTrue(basket.vouchers.all())
     request.GET = {'bundle': 'test_bundle'}
     basket = prepare_basket(request, [product])
     self.assertFalse(basket.vouchers.all())
Beispiel #29
0
    def test_voucher_offers_listing_product_found(self):
        """ Verify the endpoint returns offers data for single product range. """
        self.mock_dynamic_catalog_course_runs_api()
        product = ProductFactory(stockrecords__price_excl_tax=100)
        new_range = RangeFactory(products=[
            product,
        ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)
        request = self.prepare_offers_listing_request(voucher.code)
        response = self.endpointView(request)

        self.assertEqual(response.status_code, 200)
Beispiel #30
0
    def test_successful_response(self, product_title):
        """ Verify a successful response is returned. """
        voucher = VoucherFactory()
        order = OrderFactory(user=self.user)
        product = ProductFactory(title=product_title, categories=[])
        line = OrderLineFactory(order=order, product=product)
        order_line_vouchers = OrderLineVouchers.objects.create(line=line)
        order_line_vouchers.vouchers.add(voucher)

        response = self.client.get(reverse(self.path, args=[order.number]))
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response['content-type'], 'text/csv')