diff --git a/shopelectro/management/commands/price.py b/shopelectro/management/commands/price.py
index 7b34b437..46cd7da9 100644
--- a/shopelectro/management/commands/price.py
+++ b/shopelectro/management/commands/price.py
@@ -67,23 +67,11 @@ def context(self) -> dict:
class CategoriesFilter:
"""Categories list for particular market place."""
- # dict keys are url targets for every service
- IGNORED_CATEGORIES_MAP = defaultdict(list, {
- 'GM': ['Усилители звука для слабослышащих'],
- 'YM': ['Пиротехника'],
- # will be ignored by every category
- 'default': [
- 'Измерительные приборы', 'Новогодние вращающиеся светодиодные лампы',
- 'Новогодние лазерные проекторы', 'MP3- колонки', 'Беспроводные звонки',
- 'Радиоприёмники', 'Фонари', 'Отвертки', 'Весы электронные портативные',
- ]
- })
-
@property
def ignored(self) -> typing.List[str]:
return (
- self.IGNORED_CATEGORIES_MAP['default']
- + self.IGNORED_CATEGORIES_MAP[self.target]
+ settings.PRICE_IGNORED_CATEGORIES_MAP['default']
+ + settings.PRICE_IGNORED_CATEGORIES_MAP[self.target]
)
def __init__(self, target: str):
@@ -121,6 +109,10 @@ def qs(self) -> models.SECategoryQuerySet:
class ProductsFilter:
"""Filter offers with individual price requirements."""
+ @property
+ def ignored(self) -> typing.List[str]:
+ return settings.PRICE_IGNORED_PRODUCTS_MAP[self.target]
+
FILTERS = defaultdict(
lambda: (lambda qs: qs),
# Yandex Market feed requires picture for every offer
@@ -145,6 +137,7 @@ def qs(self) -> QuerySet:
return self.FILTERS[self.target](
models.Product.objects.active()
.filter(category__in=self.categories, price__gt=0)
+ .exclude(id__in=self.ignored)
)
diff --git a/shopelectro/settings/base.py b/shopelectro/settings/base.py
index 70ea64a5..df9fbfea 100644
--- a/shopelectro/settings/base.py
+++ b/shopelectro/settings/base.py
@@ -11,6 +11,7 @@
"""
import os
import socket
+from collections import defaultdict
from datetime import datetime
import sentry_sdk
@@ -499,6 +500,23 @@ def get_robots_content():
'SE78': 'se78.yml',
}
+PRICE_IGNORED_CATEGORIES_MAP = defaultdict(list, {
+ 'GM': ['Усилители звука для слабослышащих'],
+ 'YM': ['Пиротехника'],
+ # will be ignored by every category
+ 'default': [
+ 'Измерительные приборы', 'Новогодние вращающиеся светодиодные лампы',
+ 'Новогодние лазерные проекторы', 'MP3- колонки', 'Беспроводные звонки',
+ 'Радиоприёмники', 'Фонари', 'Отвертки', 'Весы электронные портативные',
+ ]
+})
+
+
+# contains some values for example. Local.py will contain the real values
+PRICE_IGNORED_PRODUCTS_MAP = defaultdict(list, {
+ 'YM': [1, 2, 3],
+})
+
# Number of pagination neighbors shown for page.
# If PAGINATION_NEIGHBORS = 4 and number of a page = 5,
# then will be shown neighbors by number: 3, 4, 6, 7
diff --git a/shopelectro/tests/tests_commands.py b/shopelectro/tests/tests_commands.py
index 296c4133..a5a33cca 100644
--- a/shopelectro/tests/tests_commands.py
+++ b/shopelectro/tests/tests_commands.py
@@ -11,12 +11,11 @@
import urllib.parse
import uuid
from collections import defaultdict
-from unittest import mock
from xml.etree import ElementTree
from django.conf import settings
from django.core.management import call_command
-from django.test import TestCase, tag
+from django.test import TestCase, override_settings, tag
from shopelectro.management.commands._update_catalog import (
update_products, update_tags
@@ -213,10 +212,21 @@ class GeneratePrices(TestCase):
fixtures = ['dump.json']
CATEGORY_TO_EXCLUDE = 'Category #1 of #Category #0 of #Category #1'
+ PRICE_IGNORED_CATEGORIES_MAP = defaultdict(
+ list, {'GM': [CATEGORY_TO_EXCLUDE]}
+ )
+ ignore_categories = override_settings(
+ PRICE_IGNORED_CATEGORIES_MAP=PRICE_IGNORED_CATEGORIES_MAP
+ )
+ PRODUCTS_TO_EXCLUDE = [1, 2, 3]
+ ignore_products = override_settings(
+ PRICE_IGNORED_PRODUCTS_MAP=defaultdict(list, {'YM': PRODUCTS_TO_EXCLUDE})
+ )
@classmethod
def setUpTestData(cls):
- cls.call_command_patched('price')
+ with cls.ignore_categories, cls.ignore_products:
+ call_command('price')
super(GeneratePrices, cls).setUpTestData()
cls.prices = Prices(settings.UTM_PRICE_MAP.keys())
@@ -225,18 +235,6 @@ def tearDownClass(cls):
cls.prices.remove()
super(GeneratePrices, cls).tearDownClass()
- @classmethod
- def call_command_patched(cls, name):
- """Patch with test constants and call."""
- with mock.patch(
- 'shopelectro.management.commands.price.CategoriesFilter.IGNORED_CATEGORIES_MAP',
- new_callable=mock.PropertyMock
- ) as target:
- target.return_value = defaultdict(list, {
- 'GM': [cls.CATEGORY_TO_EXCLUDE]
- })
- call_command(name)
-
def test_prices_exists(self):
"""Price command should generate various price-list files."""
price_file_min_size = 10 ** 3 # ~1kb
@@ -257,6 +255,7 @@ def test_categories_in_yandex_price(self):
Category.objects.get_categories_tree_with_pictures().count()
)
+ @ignore_categories
def test_categories_excluded_by_utm(self):
"""Price file should not contain it's excluded category."""
def find_category(categories, name):
@@ -282,6 +281,15 @@ def find_category(categories, name):
)
)
+ @ignore_products
+ def test_products_excluded_by_id(self):
+ to_ignore = set(settings.PRICE_IGNORED_PRODUCTS_MAP['YM'])
+ ignored = set(
+ offer.attrib['id']
+ for offer in self.prices['YM'].offers_node.findall('offer')
+ )
+ self.assertFalse(to_ignore.intersection(ignored))
+
def test_products_in_price(self):
products = self.prices['priceru'].offers_node
self.assertEqual(len(products), Product.objects.count())
@@ -296,10 +304,16 @@ def test_products_in_gm_price_bounds(self):
self.assertTrue(prices_are_in_bounds)
def test_products_in_yandex_price(self):
- products = self.prices['YM'].offers_node
+ origin = (
+ Product.objects
+ .exclude(id__in=self.PRODUCTS_TO_EXCLUDE)
+ .filter(page__images__isnull=False)
+ .distinct()
+ )
+ result = self.prices['YM'].offers_node
self.assertEqual(
- len(products),
- Product.objects.filter(page__images__isnull=False).distinct().count()
+ len(result),
+ origin.count()
)
def test_brands(self):
diff --git a/templates/prices/price.yml b/templates/prices/price.yml
index f84ab8d0..028ee2c3 100644
--- a/templates/prices/price.yml
+++ b/templates/prices/price.yml
@@ -41,7 +41,7 @@
{% endif %}
{% endcomment %}
- {% if not utm == 'GM' %}
+ {% if not utm == 'GM' and not utm == 'YM' %}
При заказе от {{ shop.local_delivery_cost_threshold }} руб. доставка по СПб бесплатно
{% endif %}
{% if product.brand %}{{ product.brand.name }}{% endif %}