Example #1
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')
     basket = 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)
    def test_course_entitlement_product(self):
        """Test if a course entitlement product is properly created."""

        product_class, _ = ProductClass.objects.get_or_create(
            name=COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME)
        product = ProductFactory(product_class=product_class)
        product.attr.course_key = 'foo-bar'
        product.attr.certificate_type = 'verified'
        product.attr.save()

        product.refresh_from_db()
        self.assertEqual(product.attr.course_key, 'foo-bar')
        self.assertEqual(product.attr.certificate_type, 'verified')
Example #3
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.get_or_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)
Example #4
0
    def setUp(self):
        # Timestamp in the middle of the time window
        time_delta = (DEFAULT_START_DELTA_TIME + DEFAULT_END_DELTA_TIME) / 2
        self.timestamp = datetime.datetime.now(pytz.utc) - datetime.timedelta(minutes=time_delta)

        self.payevent, __ = PaymentEventType.objects.get_or_create(name=PaymentEventTypeName.PAID)
        self.refundevent, __ = PaymentEventType.objects.get_or_create(name=PaymentEventTypeName.REFUNDED)
        self.seat_product_class, __ = ProductClass.objects.get_or_create(name=SEAT_PRODUCT_CLASS_NAME)
        self.order = OrderFactory(total_incl_tax=90, date_placed=self.timestamp)
        self.product = ProductFactory(product_class=self.seat_product_class, categories=None)
        self.line = OrderLineFactory(order=self.order, product=self.product, partner_sku='test_sku')
        self.line.save()
        self.product.save()
        self.order.save()
Example #5
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)
Example #6
0
    def test_course_entitlement_product(self):
        """Test if a course entitlement product is properly created."""

        product_class, _ = ProductClass.objects.get_or_create(
            name=COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME)
        product = ProductFactory(product_class=product_class)
        product.attr.UUID = '8724c585-acb2-42ab-986e-bc0847ef122c'
        product.attr.certificate_type = 'verified'
        product.attr.id_verification_required = False
        product.attr.save()

        product.refresh_from_db()
        self.assertEqual(product.attr.UUID,
                         '8724c585-acb2-42ab-986e-bc0847ef122c')
        self.assertEqual(product.attr.certificate_type, 'verified')
        self.assertEqual(product.attr.id_verification_required, False)
Example #7
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)
Example #8
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)
Example #9
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")
Example #10
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())
Example #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)
Example #12
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)
Example #13
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)
Example #14
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)
Example #15
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)
Example #16
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)
Example #17
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)
Example #18
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])
Example #19
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)
Example #20
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
Example #21
0
    def test_coupon_product(self):
        """Test if a coupon product is properly created."""
        coupon_product_class, _ = ProductClass.objects.get_or_create(name='coupon')
        coupon_product = ProductFactory(
            product_class=coupon_product_class,
            title='Test product'
        )
        voucher = VoucherFactory(code='MYVOUCHER')
        voucherList = CouponVouchers.objects.create(coupon=coupon_product)
        voucherList.vouchers.add(voucher)
        coupon_product.attr.coupon_voucher = voucherList

        # clean() is an Oscar validation method for products
        self.assertIsNone(coupon_product.clean())
        self.assertIsInstance(coupon_product, Product)
        self.assertEqual(coupon_product.title, 'Test product')
        self.assertEqual(coupon_product.attr.coupon_voucher.vouchers.count(), 1)
        self.assertEqual(coupon_product.attr.coupon_voucher.vouchers.first().code, 'MYVOUCHER')
 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')")
Example #24
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())
Example #25
0
 def setUp(self):
     super(StockRecordSerializerForUpdateTest, self).setUp()
     self.stock_record = StockRecordFactory(
         partner=PartnerFactory(
             short_code="dummy-partner"
         ),
         product=ProductFactory(
             categories=""
         )
     )
Example #26
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
Example #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])
Example #28
0
    def test_coupon_product(self):
        """Test if a coupon product is properly created."""
        coupon_product_class, _ = ProductClass.objects.get_or_create(
            name='coupon')
        coupon_product = ProductFactory(product_class=coupon_product_class,
                                        title='Test product')
        voucher = VoucherFactory(code='MYVOUCHER')
        voucherList = CouponVouchers.objects.create(coupon=coupon_product)
        voucherList.vouchers.add(voucher)
        coupon_product.attr.coupon_voucher = voucherList

        # clean() is an Oscar validation method for products
        self.assertIsNone(coupon_product.clean())
        self.assertIsInstance(coupon_product, Product)
        self.assertEqual(coupon_product.title, 'Test product')
        self.assertEqual(coupon_product.attr.coupon_voucher.vouchers.count(),
                         1)
        self.assertEqual(
            coupon_product.attr.coupon_voucher.vouchers.first().code,
            'MYVOUCHER')
Example #29
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')
Example #30
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())
Example #31
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)