Selaa lähdekoodia

Implemented LineDiscountRegistry

master
Lars van de Kerkhof 2 vuotta sitten
vanhempi
commit
9902021aad
2 muutettua tiedostoa jossa 87 lisäystä ja 35 poistoa
  1. 34
    34
      src/oscar/apps/basket/abstract_models.py
  2. 53
    1
      src/oscar/apps/basket/utils.py

+ 34
- 34
src/oscar/apps/basket/abstract_models.py Näytä tiedosto

@@ -14,12 +14,13 @@ from django.utils.translation import gettext_lazy as _
14 14
 from oscar.core.compat import AUTH_USER_MODEL
15 15
 from oscar.core.loading import get_class, get_classes
16 16
 from oscar.core.utils import get_default_currency, round_half_up
17
+from oscar.core.decorators import deprecated
17 18
 from oscar.models.fields.slugfield import SlugField
18 19
 from oscar.templatetags.currency_filters import currency
19 20
 
20 21
 OfferApplications = get_class("offer.results", "OfferApplications")
21 22
 Unavailable = get_class("partner.availability", "Unavailable")
22
-LineOfferConsumer = get_class("basket.utils", "LineOfferConsumer")
23
+LineDiscountRegistry = get_class("basket.utils", "LineDiscountRegistry")
23 24
 OpenBasketManager, SavedBasketManager = get_classes(
24 25
     "basket.managers", ["OpenBasketManager", "SavedBasketManager"]
25 26
 )
@@ -727,10 +728,9 @@ class AbstractLine(models.Model):
727 728
     def __init__(self, *args, **kwargs):
728 729
         super().__init__(*args, **kwargs)
729 730
         # Instance variables used to persist discount information
730
-        self.discounts = []
731 731
         # self._discount_excl_tax = D("0.00")
732 732
         # self._discount_incl_tax = D("0.00")
733
-        self.consumer = LineOfferConsumer(self)
733
+        self.discounts = LineDiscountRegistry(self)
734 734
 
735 735
     class Meta:
736 736
         abstract = True
@@ -741,6 +741,11 @@ class AbstractLine(models.Model):
741 741
         verbose_name = _("Basket line")
742 742
         verbose_name_plural = _("Basket lines")
743 743
 
744
+    @property
745
+    @deprecated
746
+    def consumer(self):
747
+        return self.discounts
748
+
744 749
     def __str__(self):
745 750
         return _(
746 751
             "Basket #%(basket_id)d, Product #%(product_id)d, quantity %(quantity)d"
@@ -765,10 +770,7 @@ class AbstractLine(models.Model):
765 770
         """
766 771
         Remove any discounts from this line.
767 772
         """
768
-        self.discounts = []
769
-        # self._discount_excl_tax = D("0.00")
770
-        # self._discount_incl_tax = D("0.00")
771
-        self.consumer = LineOfferConsumer(self)
773
+        self.discounts = LineDiscountRegistry(self)
772 774
 
773 775
     def discount(self, discount_value, affected_quantity, incl_tax=True, offer=None):
774 776
         """
@@ -786,8 +788,9 @@ class AbstractLine(models.Model):
786 788
                     "Attempting to discount the tax-exclusive price of a line "
787 789
                     "when tax-inclusive discounts are already applied"
788 790
                 )
789
-        self.discounts.append((discount_value, affected_quantity, incl_tax, offer))
790
-        self.consume(affected_quantity, offer=offer)
791
+        self.discounts.discount(discount_value, affected_quantity, incl_tax, offer)
792
+        # self.discounts.append((discount_value, affected_quantity, incl_tax, offer))
793
+        # self.consume(affected_quantity, offer=offer)
791 794
 
792 795
     def consume(self, quantity, offer=None):
793 796
         """
@@ -795,7 +798,7 @@ class AbstractLine(models.Model):
795 798
 
796 799
         Consumed items are no longer available to be used in offers.
797 800
         """
798
-        return self.consumer.consume(quantity, offer=offer)
801
+        return self.discounts.consume(quantity, offer=offer)
799 802
 
800 803
     def get_price_breakdown(self):
801 804
         """
@@ -816,14 +819,16 @@ class AbstractLine(models.Model):
816 819
         else:
817 820
             # Need to split the discount among the affected quantity
818 821
             # of products.
819
-            item_incl_tax_discount = self.discount_value / int(self.consumer.consumed())
822
+            item_incl_tax_discount = self.discount_value / int(
823
+                self.discounts.num_consumed()
824
+            )
820 825
             item_excl_tax_discount = item_incl_tax_discount * self._tax_ratio
821 826
             item_excl_tax_discount = round_half_up(item_excl_tax_discount)
822 827
             prices.append(
823 828
                 (
824 829
                     self.unit_price_incl_tax - item_incl_tax_discount,
825 830
                     self.unit_price_excl_tax - item_excl_tax_discount,
826
-                    self.consumer.consumed(),
831
+                    self.discounts.num_consumed(),
827 832
                 )
828 833
             )
829 834
             if self.quantity_without_discount:
@@ -851,16 +856,16 @@ class AbstractLine(models.Model):
851 856
     # ===============
852 857
 
853 858
     def has_offer_discount(self, offer):
854
-        return self.consumer.consumed(offer) > 0
859
+        return self.discounts.num_consumed(offer) > 0
855 860
 
856 861
     def quantity_with_offer_discount(self, offer):
857
-        return self.consumer.consumed(offer)
862
+        return self.discounts.num_consumed(offer)
858 863
 
859 864
     def quantity_without_offer_discount(self, offer):
860
-        return self.consumer.available(offer)
865
+        return self.discounts.available(offer)
861 866
 
862 867
     def is_available_for_offer_discount(self, offer):
863
-        return self.consumer.available(offer) > 0
868
+        return self.discounts.available(offer) > 0
864 869
 
865 870
     def quantity_available_for_offer(self, offer):
866 871
         return self.quantity_without_offer_discount(
@@ -872,16 +877,18 @@ class AbstractLine(models.Model):
872 877
     # ==========
873 878
 
874 879
     @property
880
+    @deprecated
875 881
     def _discount_incl_tax(self):
876
-        return sum([discount[0] for discount in self.discounts if discount[2]], 0)
882
+        return self.discounts.incl_tax
877 883
 
878 884
     @_discount_incl_tax.setter
879 885
     def _discount_incl_tax(self, value):
880 886
         raise Exception("_discount_incl_tax kan je niet setten")
881 887
 
882 888
     @property
889
+    @deprecated
883 890
     def _discount_excl_tax(self):
884
-        return sum([discount[0] for discount in self.discounts if not discount[2]], 0)
891
+        return self.discounts.excl_tax
885 892
 
886 893
     @_discount_excl_tax.setter
887 894
     def _discount_excl_tax(self, value):
@@ -889,19 +896,20 @@ class AbstractLine(models.Model):
889 896
 
890 897
     @property
891 898
     def has_discount(self):
892
-        return bool(self.consumer.consumed())
899
+        return bool(self.discounts.num_consumed())
893 900
 
894 901
     @property
895 902
     def quantity_with_discount(self):
896
-        return self.consumer.consumed()
903
+        return self.discounts.num_consumed()
897 904
 
898 905
     @property
899 906
     def quantity_without_discount(self):
900
-        return self.consumer.available()
907
+        return self.discounts.available()
901 908
 
902 909
     @property
903 910
     def discount_value(self):
904
-        return sum([discount[0] for discount in self.discounts], 0)
911
+        return self.discounts.total
912
+        # return sum([discount[0] for discount in self.discounts], 0)
905 913
         # Only one of the incl- and excl- discounts should be non-zero
906 914
         # return max(self._discount_incl_tax, self._discount_excl_tax)
907 915
 
@@ -949,12 +957,8 @@ class AbstractLine(models.Model):
949 957
         if self.line_price_excl_tax is None:
950 958
             return None
951 959
 
952
-        excl_tax_discounts = sum(
953
-            [discount[0] for discount in self.discounts if not discount[2]], 0
954
-        )
955
-        incl_tax_discounts = sum(
956
-            [discount[0] for discount in self.discounts if discount[2]], 0
957
-        )
960
+        excl_tax_discounts = self.discounts.excl_tax
961
+        incl_tax_discounts = self.discounts.incl_tax
958 962
 
959 963
         if excl_tax_discounts and self.line_price_excl_tax is not None:
960 964
             return max(0, self.line_price_excl_tax - excl_tax_discounts)
@@ -970,12 +974,8 @@ class AbstractLine(models.Model):
970 974
 
971 975
     @property
972 976
     def line_price_incl_tax_incl_discounts(self):
973
-        excl_tax_discounts = sum(
974
-            [discount[0] for discount in self.discounts if not discount[2]], 0
975
-        )
976
-        incl_tax_discounts = sum(
977
-            [discount[0] for discount in self.discounts if discount[2]], 0
978
-        )
977
+        excl_tax_discounts = self.discounts.excl_tax
978
+        incl_tax_discounts = self.discounts.incl_tax
979 979
 
980 980
         # We use whichever discount value is set.  If the discount value was
981 981
         # calculated against the tax-exclusive prices, then the line price

+ 53
- 1
src/oscar/apps/basket/utils.py Näytä tiedosto

@@ -1,9 +1,10 @@
1
-from collections import defaultdict
1
+from collections import defaultdict, namedtuple
2 2
 
3 3
 from django.contrib import messages
4 4
 from django.template.loader import render_to_string
5 5
 
6 6
 from oscar.core.loading import get_class, get_model
7
+from oscar.core.decorators import deprecated
7 8
 
8 9
 Applicator = get_class("offer.applicator", "Applicator")
9 10
 ConditionalOffer = get_model("offer", "ConditionalOffer")
@@ -126,7 +127,11 @@ class LineOfferConsumer(object):
126 127
             self._consumptions[offer.pk] += num_consumed
127 128
         return num_consumed
128 129
 
130
+    @deprecated
129 131
     def consumed(self, offer=None):
132
+        return self.num_consumed(offer)
133
+
134
+    def num_consumed(self, offer=None):
130 135
         """
131 136
         check how many items on this line have been
132 137
         consumed by an offer
@@ -193,3 +198,50 @@ class LineOfferConsumer(object):
193 198
                     return 0
194 199
 
195 200
         return max_affected_items - self.consumed(offer)
201
+
202
+
203
+DiscountApplication = namedtuple(
204
+    "DiscountApplication", ["amount", "quantity", "incl_tax", "offer"]
205
+)
206
+
207
+
208
+class LineDiscountRegistry(LineOfferConsumer):
209
+    def __init__(self, line):
210
+        super().__init__(line)
211
+        self._discounts = []
212
+        self._discount_excl_tax = None
213
+        self._discount_incl_tax = None
214
+
215
+    def discount(self, amount, quantity, incl_tax=True, offer=None):
216
+        self._discounts.append(DiscountApplication(amount, quantity, incl_tax, offer))
217
+        self.consume(quantity, offer=offer)
218
+        if incl_tax:
219
+            self._discount_incl_tax = None
220
+        else:
221
+            self._discount_excl_tax = None
222
+
223
+    @property
224
+    def excl_tax(self):
225
+        if self._discount_excl_tax is None:
226
+            self._discount_excl_tax = sum(
227
+                [d.amount for d in self._discounts if not d.incl_tax], 0
228
+            )
229
+        return self._discount_excl_tax
230
+
231
+    @property
232
+    def incl_tax(self):
233
+        if self._discount_incl_tax is None:
234
+            self._discount_incl_tax = sum(
235
+                [d.amount for d in self._discounts if d.incl_tax], 0
236
+            )
237
+        return self._discount_incl_tax
238
+
239
+    @property
240
+    def total(self):
241
+        return sum([d.amount for d in self._discounts], 0)
242
+
243
+    def all(self):
244
+        return self._discounts
245
+
246
+    def __iter__(self):
247
+        return iter(self._discounts)

Loading…
Peruuta
Tallenna