Repository: fidals/shopelectro

Issue:
Remove all wholesale processing from UI
- [ ] Remove all wholesale prices from UI
- [ ] Remove cart price recalculating
- [ ] But keep wholesale prices in DB and take them with import_db command
- [x] Add this issue to README to fast resurrect processing if it'll needed


Discussion:

Resolving patch:
diff --git a/shopelectro/cart.py b/shopelectro/cart.py
--- a/shopelectro/cart.py
+++ b/shopelectro/cart.py
@@ -1,81 +1,5 @@
-from collections import OrderedDict
-from functools import wraps
-
-from django.db.models import Model
-from django.conf import settings
-
 from ecommerce.cart import Cart
 
-from shopelectro.models import Product
-
-
-def recalculate(func):
-    @wraps(func)
-    def wrapper(*args, **kwargs):
-        recalculate_price(func(*args, **kwargs))
-    return wrapper
-
-
-def recalculate_price(cart: Cart):
-    """
-    Define what type of price should be used in Cart.
-
-    Actualize price if needed.
-    """
-    wholesale_types = OrderedDict([
-        ('wholesale_large', settings.PRICE_BOUNDS['wholesale_large']),
-        ('wholesale_medium', settings.PRICE_BOUNDS['wholesale_medium']),
-        ('wholesale_small', settings.PRICE_BOUNDS['wholesale_small']),
-    ])
-
-    product_ids = [id_ for id_, _ in cart]
-    products = Product.objects.filter(id__in=product_ids)
-
-    def get_product(id_):
-        return next((product for product in products if product.id == id_), {})
-
-    def get_product_data(price_type: str) -> list:
-        return [{
-            'id': id_,
-            'quantity': position['quantity'],
-            'price': getattr(
-                get_product(id_), price_type or 'price',
-            ),
-        } for id_, position in cart]
-
-    def get_total_price(price_type: str):
-        return sum(
-            product_data['price'] * product_data['quantity']
-            for product_data in get_product_data(price_type)
-        )
-
-    total_wholesale_prices = {
-        price_type: get_total_price(price_type)
-        for price_type in wholesale_types
-    }
-
-    def define_price_type() -> "Wholesale price type" or None:
-        def is_applicable(price_type):
-            return (
-                wholesale_types[price_type] <
-                total_wholesale_prices[price_type]
-            )
-
-        for price_type in wholesale_types:
-            if is_applicable(price_type):
-                return price_type
-
-    def set_position_prices(price_type: str):
-        """
-        Set price from Product.price.
-
-        If price_type is NoneType, then it is retail price, set price from
-        Product.price.
-        """
-        cart.update_position_prices(get_product_data(price_type))
-
-    set_position_prices(define_price_type())
-
 
 class SECart(Cart):
     """Override Cart class for Wholesale features."""
@@ -88,21 +12,6 @@ def get_position_data(self, position):
             'purchase_price': position.purchase_price,
         }
 
-    @recalculate
-    def add(self, position: Model, quantity=1):
-        super().add(position, quantity)
-        return self
-
-    @recalculate
-    def set_position_quantity(self, position: Model, quantity: int):
-        super().set_position_quantity(position, quantity)
-        return self
-
-    @recalculate
-    def remove(self, position: Model):
-        super().remove(position)
-        return self
-
     def total_revenue(self):
         return sum(
             (position['price'] - position['purchase_price']) * position['quantity']
diff --git a/shopelectro/settings/base.py b/shopelectro/settings/base.py
--- a/shopelectro/settings/base.py
+++ b/shopelectro/settings/base.py
@@ -481,12 +481,6 @@ def get_robots_content():
     ],
 }
 
-PRICE_BOUNDS = {
-    'wholesale_large': 100000,
-    'wholesale_medium': 50000,
-    'wholesale_small': 20000,
-}
-
 BRAND_TAG_GROUP_NAME = 'Производитель'
 
 # products with price lower this value should not be presented at gm.yml price
diff --git a/shopelectro/views/catalog.py b/shopelectro/views/catalog.py
--- a/shopelectro/views/catalog.py
+++ b/shopelectro/views/catalog.py
@@ -68,7 +68,6 @@ def get_context_data(self, **kwargs):
         return {
             **context_,
             **product_images,
-            'price_bounds': settings.PRICE_BOUNDS,
             'group_tags_pairs': self.product.get_params().items(),
             'tile_products': tile_products,
         }


Test patch:
diff --git a/shopelectro/management/commands/test_db.py b/shopelectro/management/commands/test_db.py
--- a/shopelectro/management/commands/test_db.py
+++ b/shopelectro/management/commands/test_db.py
@@ -19,7 +19,6 @@
 from images.models import Image, model_directory_path
 from pages.models import Page, FlatPage, PageTemplate
 from pages.utils import save_custom_pages, init_redirects_app
-
 from shopelectro import models as se_models, tests as se_tests
 
 
@@ -151,7 +150,7 @@ def create_product(parent: se_models.Category, tags_, price_factor):
                 id=self.product_id,
                 # vendor_code should be differ from id for tests.
                 vendor_code=self._product_id + 1,
-                name='Product #{} of {}'.format(price_factor, parent),
+                name=f'Product #{price_factor} of {parent}',
                 in_stock=price_factor % 3,
                 price=price_factor * 100,
                 category=parent,
diff --git a/shopelectro/tests/tests_wholesale.py b/shopelectro/tests/tests_wholesale.py
deleted file mode 100644
--- a/shopelectro/tests/tests_wholesale.py
+++ /dev/null
@@ -1,294 +0,0 @@
-from math import ceil
-
-from django.conf import settings
-from django.test import TestCase, tag
-
-from shopelectro.cart import SECart
-from shopelectro.models import Product
-
-
-@tag('fast')
-class SECartTest(TestCase):
-
-    fixtures = ['dump.json']
-
-    def __init__(self, *args, **kwargs):
-        self.item_quantity = 2
-        self.wholesale_price_type = {
-            'wholesale_large': settings.PRICE_BOUNDS['wholesale_large'],
-            'wholesale_medium': settings.PRICE_BOUNDS['wholesale_medium'],
-            'wholesale_small': settings.PRICE_BOUNDS['wholesale_small'],
-            'price': 10000
-        }
-        super().__init__(*args, **kwargs)
-
-    def setUp(self):
-        self.products = Product.objects.all()[:self.item_quantity]
-        self.first_product, self.second_product = self.products
-        self.session = self.client.session
-
-    @property
-    def cart(self):
-        """Return Cart object for test."""
-        return SECart(self.session)
-
-    def get_wholesale_data(self, price_type, products: list):
-        """Return minimal products count to get assigned price_type."""
-        bound_devider = len(products)
-
-        def get_data(product):
-            price = float(getattr(product, price_type))
-            quantity = ceil(
-                self.wholesale_price_type[price_type] / bound_devider / price)
-            return {
-                'price': price,
-                'quantity': quantity
-            }
-
-        wholesale_data = {product: get_data(product) for product in products}
-        *_, last_product = products
-        # Increment quantity, because wholesale price should be strictly
-        # more then bounds.
-        wholesale_data[last_product]['quantity'] += 1
-        return wholesale_data
-
-    def setup_for_tests(self, price_type):
-        product_data = (
-            self.get_wholesale_data(
-                price_type,
-                [self.first_product, self.second_product],
-            )
-        )
-
-        first_product = product_data[self.first_product]
-        second_product = product_data[self.second_product]
-
-        return {
-            'first_product_price': first_product['price'],
-            'second_product_price': second_product['price'],
-            'first_product_quantity': first_product['quantity'],
-            'second_product_quantity': second_product['quantity'],
-        }
-
-    def add_products_to_card(self, data):
-        self.cart.add(self.first_product, data['first_product_quantity'])
-        self.cart.add(self.second_product, data['second_product_quantity'])
-        return data
-
-    def get_set_total(self, before, after):
-        return (
-            after['first_product_price'] * before['first_product_quantity'] +
-            after['second_product_price'] * after['second_product_quantity']
-        )
-
-    def get_remove_total(self, before, after):
-        return (
-            after['first_product_price'] * before['first_product_quantity']
-        )
-
-    def get_add_total(self, after):
-        return (
-            after['first_product_price'] * after['first_product_quantity'] +
-            after['second_product_price'] * after['second_product_quantity']
-        )
-
-    def prepare_for_before_and_after_test(self, before, after):
-        before = self.setup_for_tests(before)
-        after = self.setup_for_tests(after)
-        return before, after
-
-    def prepare_remove_test(self, before, after):
-        self.add_products_to_card(before)
-        self.cart.remove(self.second_product)
-        total = self.get_remove_total(before, after)
-        return after, total
-
-    def prepare_add_test(self, after):
-        self.add_products_to_card(after)
-        total = self.get_add_total(after)
-        return after, total
-
-    def run_add_test(self, after, total_sum):
-        prices = [
-            after['first_product_price'],
-            after['second_product_price']
-        ]
-        for _, position in self.cart:
-            self.assertIn(position['price'], prices)
-        self.assertEqual(total_sum, self.cart.total_price)
-
-    def run_remove_test(self, after, total_sum):
-        for _, position in self.cart:
-            self.assertEqual(position['price'], after['first_product_price'])
-        self.assertEqual(total_sum, self.cart.total_price)
-
-    def run_dec_set_test(self, before, after):
-        self.add_products_to_card(before)
-        self.cart.set_position_quantity(
-            self.second_product, after['second_product_quantity']
-        )
-        total = self.get_set_total(before, after)
-        self.run_remove_test(after, total)
-
-    def run_inc_set_test(self, before, after):
-        self.add_products_to_card(before)
-        self.cart.set_position_quantity(
-            self.first_product, after['first_product_quantity']
-        )
-        self.cart.set_position_quantity(
-            self.second_product, after['second_product_quantity']
-        )
-        total = self.get_add_total(after)
-        self.run_add_test(after, total)
-
-    def test_add_wholesale_small(self):
-        """
-        Test changing price type after add product to card.
-
-        If the sum of prices on small wholesale is greater than
-        20 000 rub. then price for every product equated small wholesale price.
-        """
-        self.run_add_test(
-            *self.prepare_add_test(
-                self.setup_for_tests('wholesale_small')
-            )
-        )
-
-    def test_add_wholesale_medium(self):
-        """
-        Test changing price type after add product to card.
-
-        If the sum of prices on medium wholesale is greater than
-        50 000 rub. then price for every product equated medium
-        wholesale price.
-        """
-        self.run_add_test(
-            *self.prepare_add_test(
-                self.setup_for_tests('wholesale_medium')
-            )
-        )
-
-    def test_add_wholesale_large(self):
-        """
-        Test changing price type after add product to card.
-
-        If the sum of prices on large wholesale is greater than
-        100 000 rub. then price for every product equated large
-        wholesale price.
-        """
-        self.run_add_test(
-            *self.prepare_add_test(
-                self.setup_for_tests('wholesale_large')
-            )
-        )
-
-    def test_remove_wholesale_small_to_price(self):
-        """
-        Test changing price type after remove product from card.
-
-        If the sum of prices on small wholesale is less than
-        20 000 rub. then price for every product equated default price.
-        """
-        self.run_remove_test(
-            *self.prepare_remove_test(
-                *self.prepare_for_before_and_after_test(
-                    'wholesale_small', 'price'
-                )
-            )
-        )
-
-    def test_remove_wholesale_medium_to_wholesale_small(self):
-        """
-        Test changing price type after remove product from card.
-
-        If the sum of prices on medium wholesale is less than
-        50 000 rub. then price for every product equated small price.
-        """
-        self.run_remove_test(
-            *self.prepare_remove_test(
-                *self.prepare_for_before_and_after_test(
-                    'wholesale_medium', 'wholesale_small'
-                )
-            )
-        )
-
-    def test_remove_wholesale_large_to_wholesale_medium(self):
-        """
-        Test changing price type after remove product from card.
-
-        If the sum of prices on large wholesale is less than
-        100 000 rub. then price for every product equated medium price.
-        """
-        self.run_remove_test(
-            *self.prepare_remove_test(
-                *self.prepare_for_before_and_after_test(
-                    'wholesale_large', 'wholesale_medium'
-                )
-            )
-        )
-
-    def test_set_wholesale_small_to_price(self):
-        """
-        Test changing price type after set product quality in card.
-
-        If the sum of prices on small wholesale is less than
-        20 000 rub. then price for every product equated default price.
-        """
-        self.run_dec_set_test(*self.prepare_for_before_and_after_test(
-            'wholesale_small', 'price'
-        ))
-
-    def test_set_wholesale_medium_to_wholesale_small(self):
-        """
-        Test changing price type after set product quality in card.
-
-        If the sum of prices on medium wholesale is less than
-        50 000 rub. then price for every product equated small price.
-        """
-        self.run_dec_set_test(*self.prepare_for_before_and_after_test(
-            'wholesale_medium', 'wholesale_small'
-        ))
-
-    def test_set_wholesale_large_to_wholesale_medium(self):
-        """
-        Test changing price type after set product quality in card.
-
-        If the sum of prices on large wholesale is less than
-        100 000 rub. then price for every product equated medium price.
-        """
-        self.run_dec_set_test(*self.prepare_for_before_and_after_test(
-            'wholesale_large', 'wholesale_medium'
-        ))
-
-    def test_set_price_to_wholesale_small(self):
-        """
-        Test changing price type after set product quality in card.
-
-        If the sum of prices on small wholesale is less than
-        20 000 rub. then price for every product equated default price.
-        """
-        self.run_inc_set_test(*self.prepare_for_before_and_after_test(
-            'price', 'wholesale_small'
-        ))
-
-    def test_set_wholesale_small_to_wholesale_medium(self):
-        """
-        Test changing price type after set product quality in card.
-
-        If the sum of prices on medium wholesale is less than
-        50 000 rub. then price for every product equated small price.
-        """
-        self.run_inc_set_test(*self.prepare_for_before_and_after_test(
-            'wholesale_small', 'wholesale_medium'
-        ))
-
-    def test_set_wholesale_medium_to_wholesale_large(self):
-        """
-        Test changing price type after set product quality in card.
-
-        If the sum of prices on large wholesale is less than
-        100 000 rub. then price for every product equated medium price.
-        """
-        self.run_inc_set_test(*self.prepare_for_before_and_after_test(
-            'wholesale_medium', 'wholesale_large'
-        ))