Преглед изворни кода

When there are product discountable true and variant discountable false in cart in the same time, discount is calculated for variant which is incorrect. (#4102)

* fix use get_is_discountable instead is_discountable attribute from product

* add test case

* add check discount percentage in test

* Fix test case

* remove file setting

* basket add product in test

* Make the test pass

---------

Co-authored-by: Kaew <ajchariya.ung@gmail.com>
master
Voxin Muyli пре 2 година
родитељ
комит
c862b4c8d7
No account linked to committer's email address

+ 6
- 6
src/oscar/apps/catalogue/abstract_models.py Прегледај датотеку

@@ -24,6 +24,7 @@ from django.utils.translation import gettext_lazy as _
24 24
 from django.utils.translation import pgettext, pgettext_lazy
25 25
 from treebeard.mp_tree import MP_Node
26 26
 
27
+from oscar.core.decorators import deprecated
27 28
 from oscar.core.loading import get_class, get_classes, get_model
28 29
 from oscar.core.utils import slugify
29 30
 from oscar.core.validators import non_python_keyword
@@ -647,15 +648,14 @@ class AbstractProduct(models.Model):
647 648
             return self.product_class
648 649
     get_product_class.short_description = _("Product class")
649 650
 
651
+    @deprecated
650 652
     def get_is_discountable(self):
651 653
         """
652
-        At the moment, :py:attr:`.is_discountable` can't be set individually for child
653
-        products; they inherit it from their parent.
654
+        It used to be that, :py:attr:`.is_discountable` couldn't be set individually for child
655
+        products; so they had to inherit it from their parent. This is nolonger the case because
656
+        ranges can include child products as well. That make this method useless.
654 657
         """
655
-        if self.is_child:
656
-            return self.parent.is_discountable
657
-        else:
658
-            return self.is_discountable
658
+        return self.is_discountable
659 659
 
660 660
     def get_categories(self):
661 661
         """

+ 1
- 4
src/oscar/apps/offer/abstract_models.py Прегледај датотеку

@@ -805,7 +805,7 @@ class AbstractCondition(BaseOfferMixin, models.Model):
805 805
             return False
806 806
         product = line.product
807 807
         return (self.range.contains_product(product)
808
-                and product.get_is_discountable())
808
+                and product.is_discountable)
809 809
 
810 810
     def get_applicable_lines(self, offer, basket, most_expensive_first=True):
811 811
         """
@@ -829,9 +829,6 @@ class AbstractCondition(BaseOfferMixin, models.Model):
829 829
 class AbstractRange(models.Model):
830 830
     """
831 831
     Represents a range of products that can be used within an offer.
832
-
833
-    Ranges only support adding parent or stand-alone products. Offers will
834
-    consider child products automatically.
835 832
     """
836 833
     name = models.CharField(_("Name"), max_length=128, unique=True)
837 834
     slug = fields.AutoSlugField(

+ 0
- 1
tests/integration/catalogue/test_product.py Прегледај датотеку

@@ -106,7 +106,6 @@ class ChildProductTests(ProductTests):
106 106
             is_discountable=True)
107 107
         self.assertEqual("Parent product", p.get_title())
108 108
         self.assertEqual("Clothing", p.get_product_class().name)
109
-        self.assertEqual(False, p.get_is_discountable())
110 109
 
111 110
     def test_child_products_are_not_part_of_browsable_set(self):
112 111
         Product.objects.create(

+ 60
- 0
tests/integration/offer/test_absolute_benefit.py Прегледај датотеку

@@ -386,3 +386,63 @@ class TestAnAbsoluteDiscountBenefit(TestCase):
386 386
         assert line.line_price_excl_tax_incl_discounts == D(0)
387 387
         assert line.line_price_incl_tax_incl_discounts == D(0)
388 388
         assert basket.total_incl_tax == 0
389
+
390
+    def test_is_discountable_works_on_child_level(self):
391
+        rng = factories.RangeFactory(includes_all_products=True, name="klaazien")
392
+        benefit = factories.BenefitFactory(
393
+            range=rng, type=models.Benefit.PERCENTAGE, value=5, max_affected_items=100
394
+        )
395
+        condition = models.ValueCondition.objects.create(
396
+            range=rng,
397
+            type=models.Condition.COUNT,
398
+            value=1
399
+        )
400
+
401
+        factories.ConditionalOfferFactory(
402
+            priority=99999,
403
+            exclusive=False,
404
+            condition=condition,
405
+            benefit=benefit
406
+        )
407
+
408
+        basket = factories.create_basket(empty=True)
409
+
410
+        prod1 = factories.create_product(title="Gert is friends with Berrie", is_discountable=True, price=100)
411
+
412
+        parent_discountable_product = factories.create_product(structure='parent', is_discountable=True)
413
+        child = factories.create_product(
414
+            title="Undiscountable variant",
415
+            structure='child',
416
+            parent=parent_discountable_product,
417
+            is_discountable=False,
418
+            price=100
419
+        )
420
+
421
+        parent_product = factories.create_product(structure='parent', is_discountable=False)
422
+        child_discountable = factories.create_product(
423
+            title="Discountable variant ", structure='child', parent=parent_product, is_discountable=True, price=200)
424
+
425
+        basket.add_product(prod1, quantity=1)
426
+        basket.add_product(child, quantity=2)
427
+        basket.add_product(child_discountable, quantity=3)
428
+
429
+        Applicator().apply(basket)
430
+        line = basket.all_lines()
431
+        product_actual = benefit.can_apply_benefit(line[0])
432
+        assert product_actual
433
+        assert prod1.is_discountable
434
+        assert line[0].has_discount
435
+        assert line[0].discount_value == D(5)
436
+
437
+        variant_actual = benefit.can_apply_benefit(line[1])
438
+        assert not variant_actual
439
+        assert parent_discountable_product.is_discountable
440
+        assert not child.is_discountable
441
+        assert line[1].discount_value == D(0)
442
+
443
+        variant_discountable_actual = benefit.can_apply_benefit(line[2])
444
+        assert variant_discountable_actual
445
+        assert not parent_product.is_discountable
446
+        assert child_discountable.is_discountable
447
+        assert line[2].has_discount
448
+        assert line[2].discount_value == D(30)

Loading…
Откажи
Сачувај