Пример #1
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 = factories.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)
Пример #2
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])
Пример #3
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))
    def test_change_priority_of_offers_in_batches(self, offset, limit, priority):
        """Test that command changes priority of voucher offers in batches."""
        ent_offer_count = 30
        for idx in range(ent_offer_count):
            factories.ConditionalOfferFactory(
                name='ENT Offer {}'.format(idx), offer_type=ConditionalOffer.VOUCHER, priority=priority
            )

        update_offer_cnt = limit if offset + limit <= ent_offer_count else ent_offer_count - offset
        offers_list = [
            '{}. ENT Offer {}'.format(idx + 1, val) for idx, val in enumerate(range(offset, offset + update_offer_cnt))
        ]
        offer_names = '\n'.join(offers_list)
        expected = [
            (
                LOGGER_NAME,
                'WARNING',
                'Conditional offers to be updated\n{offer_names}'.format(
                    offer_names=offer_names,
                )
            )
        ]

        with patch(self.YES_NO_PATCH_LOCATION) as mocked_yes_no:
            mocked_yes_no.return_value = True
            with LogCapture(LOGGER_NAME) as log:
                call_command('change_priority_of_offers', offset=offset, limit=limit, priority=priority)
                log_msg = 'Operation completed. {} conditional offers updated successfully.'.format(update_offer_cnt)
                expected.append(
                    (
                        LOGGER_NAME,
                        'INFO',
                        log_msg
                    )
                )
                log.check(*expected)
Пример #5
0
    def test_condition_satisfied_for_enterprise_switch_off(self):
        """Verify a condition is satisfied."""
        Switch.objects.update_or_create(
            name=ENTERPRISE_OFFERS_FOR_COUPONS_SWITCH,
            defaults={'active': False})
        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)

        with patch.object(benefit, 'get_applicable_lines', return_value=[1]):
            basket.add_product(self.product)
            self.assertTrue(offer.is_condition_satisfied(basket))
Пример #6
0
 def test_creating_offer_with_null_partner(self):
     """Verify creating ConditionalOffer with no partner specified"""
     offer = factories.ConditionalOfferFactory()
     self.assertEqual(offer.partner, None)
Пример #7
0
 def test_creating_offer_with_invalid_max_global_applications(
         self, max_uses):
     """Verify creating ConditionalOffer with invalid max global applications value raises validation error."""
     with self.assertRaises(ValidationError):
         factories.ConditionalOfferFactory(max_global_applications=max_uses)
Пример #8
0
 def test_creating_offer_with_valid_max_global_applications(self):
     """Verify creating ConditionalOffer with valid max global applications value."""
     offer = factories.ConditionalOfferFactory(max_global_applications=5)
     self.assertEqual(offer.max_global_applications, 5)
Пример #9
0
 def test_creating_offer_with_invalid_email_domains(self, email_domains):
     """Verify creating ConditionalOffer with invalid email domains raises validation error."""
     with self.assertRaises(ValidationError):
         factories.ConditionalOfferFactory(email_domains=email_domains)
Пример #10
0
 def test_creating_offer_with_valid_email_domains(self, email_domains):
     """Verify creating ConditionalOffer with valid email domains."""
     offer = factories.ConditionalOfferFactory(email_domains=email_domains)
     self.assertEqual(offer.email_domains, email_domains)
Пример #11
0
 def test_creating_offer_with_null_site(self):
     """Verify creating ConditionalOffer with no site specified"""
     offer = factories.ConditionalOfferFactory()
     self.assertEqual(offer.site, None)
Пример #12
0
 def test_creating_offer_with_site(self):
     """Verify creating ConditionalOffer with site specified"""
     offer = factories.ConditionalOfferFactory(site=self.site)
     self.assertEqual(offer.site, self.site)
Пример #13
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 = {}