Пример #1
0
    def setUp(self):
        super().setUp()

        self.basket = factories.create_basket(empty=True)

        # Create range and add one product to it.
        rng = factories.RangeFactory(name='All products',
                                     includes_all_products=True)
        self.product = factories.ProductFactory()
        rng.add_product(self.product)

        # Create a non-exclusive offer #1.
        condition1 = factories.ConditionFactory(range=rng, value=D('1'))
        benefit1 = factories.BenefitFactory(range=rng, value=D('10'))
        self.offer1 = factories.ConditionalOfferFactory(
            condition=condition1,
            benefit=benefit1,
            start_datetime=now(),
            name='Test offer #1',
            exclusive=False,
        )

        # Create a non-exclusive offer #2.
        condition2 = factories.ConditionFactory(range=rng, value=D('1'))
        benefit2 = factories.BenefitFactory(range=rng, value=D('5'))
        self.offer2 = factories.ConditionalOfferFactory(
            condition=condition2,
            benefit=benefit2,
            start_datetime=now(),
            name='Test offer #2',
            exclusive=False,
        )
Пример #2
0
    def test_track_completed_discounted_order_with_voucher_with_offer(self):
        with mock.patch(
                'ecommerce.extensions.checkout.signals.track_segment_event'
        ) as mock_track:
            # Orders may be discounted by a fixed value
            fixed_benefit = 5.00
            offer_discount = 6
            product = ProductFactory(categories=[],
                                     stockrecords__price_currency='USD')
            _range = factories.RangeFactory(products=[product], )
            voucher, product = prepare_voucher(_range=_range,
                                               benefit_value=fixed_benefit,
                                               benefit_type=Benefit.FIXED)
            factories.ConditionalOfferFactory(
                offer_type=ConditionalOffer.SITE,
                benefit=factories.BenefitFactory(range=_range,
                                                 value=offer_discount),
                condition=factories.ConditionFactory(type=Condition.COVERAGE,
                                                     value=1,
                                                     range=_range))

            basket = BasketFactory(owner=self.user, site=self.site)
            basket.add_product(product)
            basket.vouchers.add(voucher)
            Applicator().apply(basket, user=basket.owner, request=self.request)

            order = factories.create_order(basket=basket, user=self.user)
            track_completed_order(None, order)
            properties = self._generate_event_properties(order, voucher)
            mock_track.assert_called_once_with(order.site, order.user,
                                               'Order Completed', properties)
Пример #3
0
    def test_coupon_applied_on_site_offer(self):
        """Coupon offer supersedes site offer."""
        self.mock_access_token_response()
        self.mock_account_api(self.request, self.user.username, data={'is_active': True})
        product_price = 100
        site_offer_discount = 20
        voucher_discount = 10

        voucher, product = prepare_voucher(benefit_value=voucher_discount)
        stockrecord = product.stockrecords.first()
        stockrecord.price_excl_tax = product_price
        stockrecord.save()

        _range = factories.RangeFactory(includes_all_products=True)
        site_offer = factories.ConditionalOfferFactory(
            offer_type=ConditionalOffer.SITE,
            benefit=factories.BenefitFactory(range=_range, value=site_offer_discount),
            condition=factories.ConditionFactory(type=Condition.COVERAGE, value=1, range=_range)
        )
        self.basket.add_product(product)
        # Only site offer is applied to the basket.
        self.assert_basket_discounts([site_offer])

        # Only the voucher offer is applied to the basket.
        self.client.post(reverse('basket:vouchers-add'), data={'code': voucher.code})
        self.assert_basket_discounts(expected_voucher_discounts=[voucher.offers.first()])

        # Site offer discount is still present after removing voucher.
        self.client.post(reverse('basket:vouchers-remove', kwargs={'pk': voucher.id}))
        self.assert_basket_discounts([site_offer])
Пример #4
0
    def test_is_range_condition_satisfied(self):
        """
        Verify that a basket satisfies a condition only when all of its products are in its range's catalog queryset.
        """
        valid_user_email = 'valid@{domain}'.format(
            domain=self.valid_sub_domain)
        basket = factories.BasketFactory(
            site=self.site, owner=UserFactory(email=valid_user_email))
        product = self.create_entitlement_product()
        another_product = self.create_entitlement_product()

        _range = factories.RangeFactory()
        _range.course_seat_types = ','.join(Range.ALLOWED_SEAT_TYPES)
        _range.catalog_query = 'uuid:{course_uuid}'.format(
            course_uuid=product.attr.UUID)
        benefit = factories.BenefitFactory(range=_range)
        offer = factories.ConditionalOfferFactory(benefit=benefit)
        self.mock_access_token_response()
        self.mock_catalog_query_contains_endpoint(
            course_run_ids=[],
            course_uuids=[product.attr.UUID],
            absent_ids=[another_product.attr.UUID],
            query=benefit.range.catalog_query,
            discovery_api_url=self.site_configuration.discovery_api_url)

        basket.add_product(product)
        self.assertTrue(offer.is_condition_satisfied(basket))

        basket.add_product(another_product)
        self.assertFalse(offer.is_condition_satisfied(basket))

        # Verify that API return values are cached
        httpretty.disable()
        self.assertFalse(offer.is_condition_satisfied(basket))
Пример #5
0
    def test_for_multiple_offers_benefits_and_conditions_not_deleted(self):

        condition = factories.ConditionFactory()
        condition_id = condition.id
        benefit = factories.BenefitFactory()
        benefit_id = benefit.id

        offer1 = factories.create_offer(name='First test offer',
                                        condition=condition)
        offer2 = factories.create_offer(name='Second test offer',
                                        condition=condition,
                                        benefit=benefit)
        offer3 = factories.create_offer(name='Third test offer',
                                        benefit=benefit)

        offer1.delete()
        self.assertTrue(
            models.Condition.objects.filter(id=condition_id).exists())

        offer2.delete()
        self.assertFalse(
            models.Condition.objects.filter(id=condition_id).exists())
        self.assertTrue(models.Benefit.objects.filter(id=benefit_id).exists())

        offer3.delete()
        self.assertFalse(models.Benefit.objects.filter(id=benefit_id).exists())
Пример #6
0
    def test_track_completed_discounted_order_with_offer(self):
        """ An event including a discount but no coupon should be sent to Segment"""
        with mock.patch(
                'ecommerce.extensions.checkout.signals.track_segment_event'
        ) as mock_track:
            # Orders may be discounted by a fixed value
            offer_discount = 5
            product = ProductFactory(categories=[],
                                     stockrecords__price_currency='USD')
            _range = factories.RangeFactory(products=[product], )
            site_offer = factories.ConditionalOfferFactory(
                offer_type=ConditionalOffer.SITE,
                benefit=factories.BenefitFactory(range=_range,
                                                 value=offer_discount),
                condition=factories.ConditionFactory(type=Condition.COVERAGE,
                                                     value=1,
                                                     range=_range))

            basket = BasketFactory(owner=self.user, site=self.site)
            basket.add_product(product)
            Applicator().apply_offers(basket, [site_offer])

            order = factories.create_order(basket=basket, user=self.user)
            track_completed_order(None, order)
            properties = self._generate_event_properties(order)
            mock_track.assert_called_once_with(order.site, order.user,
                                               'Order Completed', properties)
Пример #7
0
    def test_basket_calculate_site_offer(self):
        """ Verify successful basket calculation with a site offer """

        discount_value = 10.00
        benefit = factories.BenefitFactory(type=Benefit.PERCENTAGE,
                                           range=self.range,
                                           value=discount_value)
        condition = factories.ConditionFactory(value=3,
                                               range=self.range,
                                               type=Condition.COVERAGE)
        factories.ConditionalOfferFactory(
            name=u'Test Offer',
            benefit=benefit,
            condition=condition,
            offer_type=ConditionalOffer.SITE,
            start_datetime=datetime.datetime.now() -
            datetime.timedelta(days=1),
            end_datetime=datetime.datetime.now() + datetime.timedelta(days=2))

        response = self.client.get(self.url)

        expected = {
            'total_incl_tax_excl_discounts': self.product_total,
            'total_incl_tax': Decimal('27.00'),
            'currency': 'GBP'
        }

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data, expected)
Пример #8
0
 def test_add_multiple_products_and_use_voucher(self, usage):
     """ Verify the basket accepts multiple products and a single use voucher. """
     products = ProductFactory.create_batch(
         3, stockrecords__partner=self.partner)
     voucher = factories.VoucherFactory(usage=usage)
     product_range = factories.RangeFactory(products=products)
     voucher.offers.add(
         factories.ConditionalOfferFactory(
             benefit=factories.BenefitFactory(range=product_range),
             condition=factories.ConditionFactory(range=product_range)))
     qs = urllib.urlencode(
         {
             'sku': [
                 product.stockrecords.first().partner_sku
                 for product in products
             ],
             'code':
             voucher.code
         }, True)
     url = '{root}?{qs}'.format(root=self.path, qs=qs)
     response = self.client.get(url)
     self.assertEqual(response.status_code, 303)
     basket = response.wsgi_request.basket
     self.assertEqual(basket.status, Basket.OPEN)
     self.assertTrue(basket.contains_voucher(voucher.code))
Пример #9
0
    def test_is_single_use_range_condition_satisfied(self):
        """
        Verify that the condition for a single use coupon is only satisfied by single-product baskets.
        """
        valid_user_email = 'valid@{domain}'.format(domain=self.valid_sub_domain)
        basket = factories.BasketFactory(site=self.site, owner=factories.UserFactory(email=valid_user_email))
        product1 = self.create_entitlement_product()
        product2 = self.create_entitlement_product()

        _range = factories.RangeFactory()
        _range.course_seat_types = ','.join(Range.ALLOWED_SEAT_TYPES)
        _range.catalog_query = 'uuid:*'
        benefit = factories.BenefitFactory(range=_range)
        offer = factories.ConditionalOfferFactory(benefit=benefit)
        offer.set_voucher(
            factories.VoucherFactory(usage='Single-use')
        )
        self.mock_access_token_response()
        self.mock_catalog_query_contains_endpoint(
            course_run_ids=[], course_uuids=[product1.attr.UUID, product2.attr.UUID], absent_ids=[],
            query=benefit.range.catalog_query, discovery_api_url=self.site_configuration.discovery_api_url
        )

        # Verify that each product individually satisfies the condition
        basket.add_product(product1)
        self.assertTrue(offer.is_condition_satisfied(basket))

        basket.flush()
        basket.add_product(product2)
        self.assertTrue(offer.is_condition_satisfied(basket))

        # Verify that the offer cannot be applied to a multi-product basket
        basket.add_product(product1)
        self.assertFalse(offer.is_condition_satisfied(basket))
Пример #10
0
    def setUp(self):
        super(BenefitTests, self).setUp()

        _range = factories.RangeFactory(course_seat_types=','.join(
            Range.ALLOWED_SEAT_TYPES[1:]),
                                        catalog_query='uuid:*')
        self.benefit = factories.BenefitFactory(range=_range)
        self.offer = factories.ConditionalOfferFactory(benefit=self.benefit)
        self.user = UserFactory()
Пример #11
0
    def setUp(self):
        super(ConditionalOfferTests, self).setUp()

        self.email_domains = 'example.com'
        self.product = factories.ProductFactory()
        _range = factories.RangeFactory(products=[
            self.product,
        ])

        self.offer = ConditionalOffer.objects.create(
            condition=factories.ConditionFactory(value=1, range=_range),
            benefit=factories.BenefitFactory(),
            email_domains=self.email_domains)
Пример #12
0
    def setUp(self):
        super(ConditionalOfferTests, self).setUp()

        self.valid_domain = 'example.com'
        self.valid_sub_domain = 'sub.example2.com'
        self.email_domains = '{domain1},{domain2}'.format(
            domain1=self.valid_domain, domain2=self.valid_sub_domain)
        self.product = factories.ProductFactory()
        _range = factories.RangeFactory(products=[
            self.product,
        ])

        self.offer = ConditionalOffer.objects.create(
            condition=factories.ConditionFactory(value=1, range=_range),
            benefit=factories.BenefitFactory(),
            email_domains=self.email_domains)
Пример #13
0
    def test_condition_not_satisfied_for_enterprise(self):
        """Verify a condition is not satisfied."""
        valid_user_email = 'valid@{domain}'.format(domain=self.valid_sub_domain)
        basket = factories.BasketFactory(site=self.site, owner=UserFactory(email=valid_user_email))

        _range = factories.RangeFactory(
            products=[self.product, ],
            course_seat_types='verified',
            enterprise_customer=str(uuid4()),
            catalog_query='*:*'
        )
        benefit = factories.BenefitFactory(range=_range)
        offer = factories.ConditionalOfferFactory(benefit=benefit)

        basket.add_product(self.product)
        self.assertFalse(offer.is_condition_satisfied(basket))
Пример #14
0
    def test_condition_not_satisfied_for_enterprise_switch_on(self):
        """Verify a condition is not satisfied."""
        Switch.objects.update_or_create(
            name=ENTERPRISE_OFFERS_FOR_COUPONS_SWITCH,
            defaults={'active': True})
        valid_user_email = 'valid@{domain}'.format(
            domain=self.valid_sub_domain)
        basket = factories.BasketFactory(
            site=self.site,
            owner=factories.UserFactory(email=valid_user_email))

        _range = factories.RangeFactory(products=[
            self.product,
        ],
                                        course_seat_types='verified',
                                        enterprise_customer=str(
                                            uuid4()).decode('utf-8'),
                                        catalog_query='*:*')
        benefit = factories.BenefitFactory(range=_range)
        offer = factories.ConditionalOfferFactory(benefit=benefit)

        basket.add_product(self.product)
        self.assertFalse(offer.is_condition_satisfied(basket))
Пример #15
0
    def test_value(self):
        with self.assertRaises(ValidationError):
            factories.BenefitFactory(value=110)

        with self.assertRaises(ValidationError):
            factories.BenefitFactory(value=-10)
Пример #16
0
 def test_range(self):
     with self.assertRaises(ValidationError):
         factories.BenefitFactory(range=None)
Пример #17
0
    def setUp(self):
        super().setUp()

        self.basket = factories.create_basket(empty=True)

        # Create range and add one product to it.
        rng = factories.RangeFactory(name='All products', includes_all_products=True)
        self.product = factories.ProductFactory()
        rng.add_product(self.product)

        # Create offer #1.
        condition1 = factories.ConditionFactory(
            range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('2'),
        )
        benefit1 = factories.BenefitFactory(
            range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None,
        )
        self.offer1 = factories.ConditionalOfferFactory(
            condition=condition1, benefit=benefit1,
            slug='offer-1',
            start_datetime=now(),
            name='Test offer #1',
            priority=1,
        )

        # Create offer #2.
        condition2 = factories.ConditionFactory(
            range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('1'),
        )
        benefit2 = factories.BenefitFactory(
            range=rng, type=factories.BenefitFactory._meta.model.PERCENTAGE, value=D('5'),
        )
        self.offer2 = factories.ConditionalOfferFactory(
            condition=condition2,
            benefit=benefit2,
            slug='offer-2',
            start_datetime=now(),
            name='Test offer #2',
        )

        # Create offer #3.
        condition3 = factories.ConditionFactory(
            range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('1'),
        )
        benefit3 = factories.BenefitFactory(
            range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None,
        )
        self.offer3 = factories.ConditionalOfferFactory(
            condition=condition3,
            benefit=benefit3,
            slug='offer-3',
            start_datetime=now(),
            name='Test offer #3',
            exclusive=False,
        )

        # Create offer #4.
        condition4 = factories.ConditionFactory(
            range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('1'),
        )
        benefit4 = factories.BenefitFactory(
            range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None,
        )
        self.offer4 = factories.ConditionalOfferFactory(
            condition=condition4,
            benefit=benefit4,
            slug='offer-4',
            start_datetime=now(),
            name='Test offer #4',
            exclusive=False,
            priority=3,
        )
    def setUp(self):
        super().setUp()

        self.basket = factories.create_basket(empty=True)

        # Create range and add one product to it.
        rng = factories.RangeFactory(name='All products',
                                     includes_all_products=True)
        self.product = factories.ProductFactory()
        rng.add_product(self.product)

        # Create offer #1.
        condition1 = factories.ConditionFactory(
            range=rng,
            type=factories.ConditionFactory._meta.model.COUNT,
            value=D('2'),
        )
        benefit1 = factories.BenefitFactory(
            range=rng,
            type=factories.BenefitFactory._meta.model.MULTIBUY,
            value=None,
        )
        self.offer1 = factories.ConditionalOfferFactory(
            condition=condition1,
            benefit=benefit1,
            slug='offer-1',
            start_datetime=now(),
            name='Test offer #1',
            priority=1,
        )

        # Create offer #2.
        condition2 = factories.ConditionFactory(
            range=rng,
            type=factories.ConditionFactory._meta.model.VALUE,
            value=D('1.99'),
        )
        benefit2 = factories.BenefitFactory(
            range=rng,
            type=factories.BenefitFactory._meta.model.MULTIBUY,
            value=None,
        )
        self.offer2 = factories.ConditionalOfferFactory(
            condition=condition2,
            benefit=benefit2,
            slug='offer-2',
            start_datetime=now(),
            name='Test offer #2',
        )

        # Create offer #3.
        condition3 = factories.ConditionFactory(
            range=rng,
            type=factories.ConditionFactory._meta.model.COVERAGE,
            value=1,
        )
        benefit3 = factories.BenefitFactory(
            range=rng,
            type=factories.BenefitFactory._meta.model.MULTIBUY,
            value=None,
        )
        self.offer3 = factories.ConditionalOfferFactory(
            condition=condition3,
            benefit=benefit3,
            slug='offer-3',
            start_datetime=now(),
            name='Test offer #3',
        )

        # Prepare `BasketView` to use `get_upsell_messages` method in tests.
        self.view = BasketView()
        self.view.request = RequestFactory().get(reverse('basket:summary'))
        self.view.request.user = factories.UserFactory()
        self.view.args = []
        self.view.kwargs = {}