|
|
@@ -23,12 +23,14 @@ from treebeard.mp_tree import MP_Node
|
|
23
|
23
|
|
|
24
|
24
|
from oscar.core.decorators import deprecated
|
|
25
|
25
|
from oscar.core.utils import slugify
|
|
26
|
|
-from oscar.core.loading import get_classes, get_model
|
|
|
26
|
+from oscar.core.loading import get_classes, get_model, get_class
|
|
27
|
27
|
from oscar.models.fields import NullCharField, AutoSlugField
|
|
28
|
28
|
|
|
29
|
29
|
ProductManager, BrowsableProductManager = get_classes(
|
|
30
|
30
|
'catalogue.managers', ['ProductManager', 'BrowsableProductManager'])
|
|
31
|
31
|
|
|
|
32
|
+Selector = get_class('partner.strategy', 'Selector')
|
|
|
33
|
+
|
|
32
|
34
|
|
|
33
|
35
|
@python_2_unicode_compatible
|
|
34
|
36
|
class AbstractProductClass(models.Model):
|
|
|
@@ -480,32 +482,53 @@ class AbstractProduct(models.Model):
|
|
480
|
482
|
pairs = [attribute.summary() for attribute in attributes]
|
|
481
|
483
|
return ", ".join(pairs)
|
|
482
|
484
|
|
|
|
485
|
+ # The two properties below are deprecated because determining minimum
|
|
|
486
|
+ # price is not as trivial as it sounds considering multiple stockrecords,
|
|
|
487
|
+ # currencies, tax, etc.
|
|
|
488
|
+ # The current implementation is very naive and only works for a limited
|
|
|
489
|
+ # set of use cases.
|
|
|
490
|
+ # At the very least, we should pass in the request and
|
|
|
491
|
+ # user. Hence, it's best done as an extension to a Strategy class.
|
|
|
492
|
+ # Once that is accomplished, these properties should be removed.
|
|
|
493
|
+
|
|
483
|
494
|
@property
|
|
|
495
|
+ @deprecated
|
|
484
|
496
|
def min_child_price_incl_tax(self):
|
|
485
|
497
|
"""
|
|
486
|
|
- Return minimum child product price including tax
|
|
|
498
|
+ Return minimum child product price including tax.
|
|
487
|
499
|
"""
|
|
488
|
|
- return self._min_child_price('price_incl_tax')
|
|
|
500
|
+ return self._min_child_price('incl_tax')
|
|
489
|
501
|
|
|
490
|
502
|
@property
|
|
|
503
|
+ @deprecated
|
|
491
|
504
|
def min_child_price_excl_tax(self):
|
|
492
|
505
|
"""
|
|
493
|
|
- Return minimum child product price excluding tax
|
|
|
506
|
+ Return minimum child product price excluding tax.
|
|
|
507
|
+
|
|
|
508
|
+ This is a very naive approach; see the deprecation notice above. And
|
|
|
509
|
+ only use it for display purposes (e.g. "new Oscar shirt, prices
|
|
|
510
|
+ starting from $9.50").
|
|
494
|
511
|
"""
|
|
495
|
|
- return self._min_child_price('price_excl_tax')
|
|
|
512
|
+ return self._min_child_price('excl_tax')
|
|
496
|
513
|
|
|
497
|
|
- def _min_child_price(self, property):
|
|
|
514
|
+ def _min_child_price(self, prop):
|
|
498
|
515
|
"""
|
|
499
|
|
- Return minimum child product price
|
|
|
516
|
+ Return minimum child product price.
|
|
|
517
|
+
|
|
|
518
|
+ This is for visual purposes only. It ignores currencies, most of the
|
|
|
519
|
+ Strategy logic for selecting stockrecords, knows nothing about the
|
|
|
520
|
+ current user or request, etc. It's only here to ensure
|
|
|
521
|
+ backwards-compatibility; the previous implementation wasn't any
|
|
|
522
|
+ better.
|
|
500
|
523
|
"""
|
|
501
|
|
- prices = []
|
|
502
|
|
- for child in self.children.all():
|
|
503
|
|
- if child.has_stockrecords:
|
|
504
|
|
- prices.append(getattr(child.stockrecord, property))
|
|
505
|
|
- if not prices:
|
|
506
|
|
- return None
|
|
507
|
|
- prices.sort()
|
|
508
|
|
- return prices[0]
|
|
|
524
|
+ strategy = Selector().strategy()
|
|
|
525
|
+
|
|
|
526
|
+ children_stock = strategy.select_children_stockrecords(self)
|
|
|
527
|
+ prices = [
|
|
|
528
|
+ strategy.pricing_policy(child, stockrecord)
|
|
|
529
|
+ for child, stockrecord in children_stock]
|
|
|
530
|
+ raw_prices = sorted([getattr(price, prop) for price in prices])
|
|
|
531
|
+ return raw_prices[0] if raw_prices else None
|
|
509
|
532
|
|
|
510
|
533
|
# The properties below are based on deprecated naming conventions
|
|
511
|
534
|
|