Ejemplo n.º 1
0
 def setUp(self):
     self.applicator = Applicator()
     self.basket = BasketFactory()
     rng = RangeFactory(includes_all_products=True)
     self.condition = ConditionFactory(
         range=rng,
         type=ConditionFactory._meta.model.VALUE,
         value=D('100'),
         proxy_class=None)
     self.benefit = BenefitFactory(range=rng,
                                   type=BenefitFactory._meta.model.FIXED,
                                   value=D('10'),
                                   max_affected_items=1)
Ejemplo n.º 2
0
 def apply_20percent_shipping_offer(self):
     """Shipping offer 20% off"""
     range = Range.objects.create(name="All products range",
                                  includes_all_products=True)
     benefit = Benefit.objects.create(
         range=range, type=Benefit.SHIPPING_PERCENTAGE, value=20)
     offer = factories.create_offer(range=range, benefit=benefit)
     Applicator().apply_offers(self.basket, [offer])
     return offer
    def setUp(self):
        self.condition_product = factories.ProductFactory()
        condition_range = factories.RangeFactory()
        condition_range.add_product(self.condition_product)
        self.condition = models.CountCondition.objects.create(
            range=condition_range, type=models.Condition.COUNT, value=2)

        self.benefit_product = factories.ProductFactory()
        benefit_range = factories.RangeFactory()
        benefit_range.add_product(self.benefit_product)
        self.benefit = models.AbsoluteDiscountBenefit.objects.create(
            range=benefit_range, type=models.Benefit.FIXED, value=D('3.00'))

        self.offer = models.ConditionalOffer(id=1,
                                             condition=self.condition,
                                             benefit=self.benefit)
        self.basket = factories.create_basket(empty=True)

        self.applicator = Applicator()
class TestAnAbsoluteDiscountAppliedWithCountConditionOnDifferentRange(
        TestCase):
    def setUp(self):
        self.condition_product = factories.ProductFactory()
        condition_range = factories.RangeFactory()
        condition_range.add_product(self.condition_product)
        self.condition = models.CountCondition.objects.create(
            range=condition_range, type=models.Condition.COUNT, value=2)

        self.benefit_product = factories.ProductFactory()
        benefit_range = factories.RangeFactory()
        benefit_range.add_product(self.benefit_product)
        self.benefit = models.AbsoluteDiscountBenefit.objects.create(
            range=benefit_range, type=models.Benefit.FIXED, value=D('3.00'))

        self.offer = models.ConditionalOffer(id=1,
                                             condition=self.condition,
                                             benefit=self.benefit)
        self.basket = factories.create_basket(empty=True)

        self.applicator = Applicator()

    def test_succcessful_application_consumes_correctly(self):
        add_product(self.basket, product=self.condition_product, quantity=2)
        add_product(self.basket, product=self.benefit_product, quantity=1)

        self.applicator.apply_offers(self.basket, [self.offer])

        discounts = self.basket.offer_applications.offer_discounts
        self.assertEqual(len(discounts), 1)
        self.assertEqual(discounts[0]['freq'], 1)

    def test_condition_is_consumed_correctly(self):
        # Testing an error case reported on the mailing list
        add_product(self.basket, product=self.condition_product, quantity=3)
        add_product(self.basket, product=self.benefit_product, quantity=2)

        self.applicator.apply_offers(self.basket, [self.offer])

        discounts = self.basket.offer_applications.offer_discounts
        self.assertEqual(len(discounts), 1)
        self.assertEqual(discounts[0]['freq'], 1)
Ejemplo n.º 5
0
    def test_get_site_offers(self):
        models.ConditionalOffer.objects.create(
            name="globaloffer",
            condition=self.condition,
            benefit=self.benefit,
            offer_type=models.ConditionalOffer.SITE)
        models.ConditionalOffer.objects.create(
            name="sessionoffer",
            condition=self.condition,
            benefit=self.benefit,
            offer_type=models.ConditionalOffer.SESSION)

        site_offers = Applicator().get_site_offers()
        # Only one offer should be returned
        self.assertEqual(len(site_offers), 1)
        self.assertEqual(site_offers[0].name, "globaloffer")
Ejemplo n.º 6
0
class TestOfferApplicator(TestCase):
    def setUp(self):
        self.applicator = Applicator()
        self.basket = BasketFactory()
        rng = RangeFactory(includes_all_products=True)
        self.condition = ConditionFactory(
            range=rng,
            type=ConditionFactory._meta.model.VALUE,
            value=D('100'),
            proxy_class=None)
        self.benefit = BenefitFactory(range=rng,
                                      type=BenefitFactory._meta.model.FIXED,
                                      value=D('10'),
                                      max_affected_items=1)

    def test_applies_offer_multiple_times_by_default(self):
        add_product(self.basket, D('100'), 5)
        offer = ConditionalOfferFactory(pk=1,
                                        condition=self.condition,
                                        benefit=self.benefit)
        self.applicator.apply_offers(self.basket, [offer])
        applications = self.basket.offer_applications.applications
        self.assertEqual(5, applications[1]['freq'])

    def test_respects_maximum_applications_field(self):
        add_product(self.basket, D('100'), 5)
        offer = ConditionalOfferFactory(pk=1,
                                        condition=self.condition,
                                        benefit=self.benefit,
                                        max_basket_applications=1)
        self.applicator.apply_offers(self.basket, [offer])
        applications = self.basket.offer_applications.applications
        self.assertEqual(1, applications[1]['freq'])

    def test_uses_offers_in_order_of_descending_priority(self):
        self.applicator.get_site_offers = Mock(return_value=[
            models.ConditionalOffer(name="offer1",
                                    condition=self.condition,
                                    benefit=self.benefit,
                                    priority=1)
        ])

        self.applicator.get_user_offers = Mock(return_value=[
            models.ConditionalOffer(name="offer2",
                                    condition=self.condition,
                                    benefit=self.benefit,
                                    priority=-1)
        ])

        offers = self.applicator.get_offers(self.basket)
        priorities = [offer.priority for offer in offers]
        self.assertEqual(sorted(priorities, reverse=True), priorities)

    def test_get_site_offers(self):
        models.ConditionalOffer.objects.create(
            name="globaloffer",
            condition=self.condition,
            benefit=self.benefit,
            offer_type=models.ConditionalOffer.SITE)
        models.ConditionalOffer.objects.create(
            name="sessionoffer",
            condition=self.condition,
            benefit=self.benefit,
            offer_type=models.ConditionalOffer.SESSION)

        site_offers = Applicator().get_site_offers()
        # Only one offer should be returned
        self.assertEqual(len(site_offers), 1)
        self.assertEqual(site_offers[0].name, "globaloffer")
Ejemplo n.º 7
0
class TestBasketLineForm(TestCase):
    def setUp(self):
        self.applicator = Applicator()
        rng = RangeFactory(includes_all_products=True)
        self.condition = ConditionFactory(
            range=rng,
            type=ConditionFactory._meta.model.VALUE,
            value=D('100'),
            proxy_class=None)
        self.benefit = BenefitFactory(range=rng,
                                      type=BenefitFactory._meta.model.FIXED,
                                      value=D('10'),
                                      max_affected_items=1)
        self.basket = factories.create_basket()
        self.line = self.basket.all_lines()[0]

    def mock_availability_return_value(self, is_available, reason=''):
        policy = self.line.purchase_info.availability
        policy.is_purchase_permitted = mock.MagicMock(
            return_value=(is_available, reason))

    def build_form(self, quantity=None):
        if quantity is None:
            quantity = self.line.quantity
        return forms.BasketLineForm(strategy=self.basket.strategy,
                                    data={'quantity': quantity},
                                    instance=self.line)

    def test_enforces_availability_policy_for_valid_quantities(self):
        self.mock_availability_return_value(True)
        form = self.build_form()
        self.assertTrue(form.is_valid())

    def test_enforces_availability_policy_for_invalid_quantities(self):
        self.mock_availability_return_value(False, "Some reason")
        form = self.build_form()
        self.assertFalse(form.is_valid())
        self.assertEqual(form.errors['quantity'], ['Some reason'])

    def test_skips_availability_policy_for_zero_quantities(self):
        self.mock_availability_return_value(True)
        form = self.build_form(quantity=0)
        self.assertTrue(form.is_valid())

    def test_enforces_max_line_quantity_for_new_product(self):
        invalid_qty = settings.IZI_MAX_BASKET_QUANTITY_THRESHOLD + 1
        form = self.build_form(quantity=invalid_qty)
        self.assertFalse(form.is_valid())

    @override_settings(IZI_MAX_BASKET_QUANTITY_THRESHOLD=10)
    def test_enforce_max_line_quantity_for_existing_product(self):
        self.basket.flush()
        product = factories.create_product(num_in_stock=20)
        add_product(self.basket, D('100'), 4, product)
        self.line = self.basket.all_lines()[0]
        form = self.build_form(quantity=6)
        self.assertTrue(form.is_valid())
        form.save()
        form = self.build_form(quantity=11)
        self.assertFalse(form.is_valid())

    def test_line_quantity_max_attribute_per_num_available(self):
        self.basket.flush()
        product = factories.create_product(num_in_stock=20)
        add_product(self.basket, D('100'), 4, product)
        self.line = self.basket.all_lines()[0]
        form = self.build_form()
        self.assertIn('max="20"', str(form['quantity']))

    @override_settings(IZI_MAX_BASKET_QUANTITY_THRESHOLD=10)
    def test_line_quantity_max_attribute_per_basket_threshold(self):
        self.basket.flush()
        product = factories.create_product(num_in_stock=20)
        add_product(self.basket, D('100'), 4, product)
        self.line = self.basket.all_lines()[0]
        form = self.build_form()
        self.assertIn('max="6"', str(form['quantity']))

    def test_basketline_formset_ordering(self):
        # when we use a unordered queryset in the Basketlineformset, the
        # discounts will be lost because django will query the database
        # again to enforce ordered results
        add_product(self.basket, D('100'), 5)
        offer = ConditionalOfferFactory(pk=1,
                                        condition=self.condition,
                                        benefit=self.benefit)

        # now we force an unordered queryset so we can see that our discounts
        # will disappear due to a new ordering query (see django/forms/model.py)
        default_line_ordering = Line._meta.ordering
        Line._meta.ordering = []
        self.basket._lines = self.basket.lines.all()

        self.applicator.apply_offers(self.basket, [offer])
        formset = formsets.BasketLineFormSet(strategy=self.basket.strategy,
                                             queryset=self.basket.all_lines())

        # the discount is in all_lines():
        self.assertTrue(self.basket.all_lines()[0].has_discount)

        # but not in the formset
        self.assertFalse(formset.forms[0].instance.has_discount)

        # Restore the ordering on the line
        Line._meta.ordering = default_line_ordering

        # clear the cached lines and apply the offer again
        self.basket._lines = None
        self.applicator.apply_offers(self.basket, [offer])

        formset = formsets.BasketLineFormSet(strategy=self.basket.strategy,
                                             queryset=self.basket.all_lines())
        self.assertTrue(formset.forms[0].instance.has_discount)