diff --git a/apps/advertisement/models.py b/apps/advertisement/models.py index 920e3389..66cd0024 100644 --- a/apps/advertisement/models.py +++ b/apps/advertisement/models.py @@ -22,6 +22,10 @@ class AdvertisementQuerySet(models.QuerySet): """Filter Advertisement by page type.""" return self.filter(page_type__name=page_type) + def by_country(self, code: str): + """Filter Advertisement by country code.""" + return self.filter(sites__country__code=code) + def by_locale(self, locale): """Filter by locale.""" return self.filter(target_languages__locale=locale) diff --git a/apps/advertisement/serializers/common.py b/apps/advertisement/serializers/common.py index 0adb74f9..9caee0c2 100644 --- a/apps/advertisement/serializers/common.py +++ b/apps/advertisement/serializers/common.py @@ -11,14 +11,11 @@ from main.models import SiteSettings class AdvertisementBaseSerializer(serializers.ModelSerializer): """Base serializer for model Advertisement.""" - languages = LanguageSerializer(many=True, read_only=True, - source='target_languages') target_languages = serializers.PrimaryKeyRelatedField( queryset=Language.objects.all(), many=True, write_only=True ) - sites = SiteShortSerializer(many=True, read_only=True) target_sites = serializers.PrimaryKeyRelatedField( queryset=SiteSettings.objects.all(), many=True, @@ -33,9 +30,7 @@ class AdvertisementBaseSerializer(serializers.ModelSerializer): 'uuid', 'url', 'block_level', - 'languages', 'target_languages', - 'sites', 'target_sites', 'start', 'end', diff --git a/apps/advertisement/views/common.py b/apps/advertisement/views/common.py index 43c6e965..02c61873 100644 --- a/apps/advertisement/views/common.py +++ b/apps/advertisement/views/common.py @@ -28,5 +28,8 @@ class AdvertisementPageTypeListView(AdvertisementBaseView, generics.ListAPIView) product_type = self.kwargs.get('page_type') qs = super(AdvertisementPageTypeListView, self).get_queryset() if product_type: - return qs.by_page_type(product_type) + return qs.by_page_type(product_type) \ + .by_country(self.request.country_code) \ + .by_locale(self.request.locale) \ + .distinct('id') return qs.none() diff --git a/apps/advertisement/views/web.py b/apps/advertisement/views/web.py index db1cfde8..a9e527a0 100644 --- a/apps/advertisement/views/web.py +++ b/apps/advertisement/views/web.py @@ -7,3 +7,4 @@ class AdvertisementPageTypeWebListView(AdvertisementPageTypeListView): """Advertisement mobile list view.""" serializer_class = AdvertisementPageTypeWebListSerializer + diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 52d7ae69..5c77ccbf 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -450,13 +450,13 @@ class EstablishmentSimilarSerializer(EstablishmentBaseSerializer): address = AddressDetailSerializer(read_only=True) schedule = ScheduleRUDSerializer(many=True, allow_null=True) - establishment_type = EstablishmentTypeGeoSerializer() + type = EstablishmentTypeGeoSerializer(source='establishment_type') artisan_category = TagBaseSerializer(many=True, allow_null=True) class Meta(EstablishmentBaseSerializer.Meta): fields = EstablishmentBaseSerializer.Meta.fields + [ 'schedule', - 'establishment_type', + 'type', 'artisan_category', ] diff --git a/apps/location/filters.py b/apps/location/filters.py new file mode 100644 index 00000000..5e95db44 --- /dev/null +++ b/apps/location/filters.py @@ -0,0 +1,24 @@ +from django.core.validators import EMPTY_VALUES +from django_filters import rest_framework as filters + +from location import models + + +class CityBackFilter(filters.FilterSet): + """Employee filter set.""" + + search = filters.CharFilter(method='search_by_name') + + class Meta: + """Meta class.""" + + model = models.City + fields = ( + 'search', + ) + + def search_by_name(self, queryset, name, value): + """Search by name or last name.""" + if value not in EMPTY_VALUES: + return queryset.search_by_name(value) + return queryset diff --git a/apps/location/models.py b/apps/location/models.py index fd023443..dc7834c9 100644 --- a/apps/location/models.py +++ b/apps/location/models.py @@ -5,6 +5,9 @@ from django.db.models.signals import post_save from django.db.transaction import on_commit from django.dispatch import receiver from django.utils.translation import gettext_lazy as _ +from functools import reduce +from typing import List + from translation.models import Language from utils.models import (ProjectBaseMixin, SVGImageMixin, TJSONField, @@ -92,6 +95,18 @@ class Region(models.Model): class CityQuerySet(models.QuerySet): """Extended queryset for City model.""" + def _generic_search(self, value, filter_fields_names: List[str]): + """Generic method for searching value in specified fields""" + filters = [ + {f'{field}__icontains': value} + for field in filter_fields_names + ] + return self.filter(reduce(lambda x, y: x | y, [models.Q(**i) for i in filters])) + + def search_by_name(self, value): + """Search by name or last_name.""" + return self._generic_search(value, ['name', 'code', 'postal_code']) + def by_country_code(self, code): """Return establishments by country code""" return self.filter(country__code=code) diff --git a/apps/location/views/back.py b/apps/location/views/back.py index 4d420154..8406dee3 100644 --- a/apps/location/views/back.py +++ b/apps/location/views/back.py @@ -9,6 +9,8 @@ from rest_framework.permissions import IsAuthenticatedOrReadOnly from django.shortcuts import get_object_or_404 from utils.serializers import ImageBaseSerializer +from location import filters + # Address @@ -31,6 +33,8 @@ class CityListCreateView(common.CityViewMixin, generics.ListCreateAPIView): """Create view for model City.""" serializer_class = serializers.CitySerializer permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin] + queryset = models.City.objects.all() + filter_class = filters.CityBackFilter class CityRUDView(common.CityViewMixin, generics.RetrieveUpdateDestroyAPIView): diff --git a/apps/product/management/commands/add_product_tag.py b/apps/product/management/commands/add_product_tag.py index 6377fcac..01f5d7f7 100644 --- a/apps/product/management/commands/add_product_tag.py +++ b/apps/product/management/commands/add_product_tag.py @@ -7,7 +7,7 @@ from tqdm import tqdm class Command(BaseCommand): - help = '''Add add product tags networks from old db to new db. + help = '''Add product tags networks from old db to new db. Run after add_product!!!''' def category_sql(self): @@ -101,14 +101,12 @@ class Command(BaseCommand): p.tags.clear() print('End clear tags product') - def remove_tags(self): print('Begin delete many tags') Tag.objects.\ filter(news__isnull=True, establishments__isnull=True).delete() print('End delete many tags') - def product_sql(self): with connections['legacy'].cursor() as cursor: cursor.execute(''' diff --git a/apps/product/management/commands/check_serial_number.py b/apps/product/management/commands/check_serial_number.py new file mode 100644 index 00000000..d9caf69a --- /dev/null +++ b/apps/product/management/commands/check_serial_number.py @@ -0,0 +1,20 @@ +from django.core.management.base import BaseCommand +from tag.models import Tag, TagCategory +from tqdm import tqdm + + +class Command(BaseCommand): + help = '''Check product serial number from old db to new db. + Run after add_product_tag!!!''' + + def check_serial_number(self): + category = TagCategory.objects.get(index_name='serial_number') + tags = Tag.objects.filter(category=category, products__isnull=False) + for tag in tqdm(tags, desc='Update serial number for product'): + tag.products.all().update(serial_number=tag.value) + tag.products.clear() + + self.stdout.write(self.style.WARNING(f'Check serial number product end.')) + + def handle(self, *args, **kwargs): + self.check_serial_number() diff --git a/apps/product/migrations/0019_product_serial_number.py b/apps/product/migrations/0019_product_serial_number.py new file mode 100644 index 00000000..eb8bef34 --- /dev/null +++ b/apps/product/migrations/0019_product_serial_number.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.7 on 2019-11-21 09:24 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0018_purchasedproduct'), + ] + + operations = [ + migrations.AddField( + model_name='product', + name='serial_number', + field=models.CharField(default=None, max_length=255, null=True, verbose_name='Serial number'), + ), + ] diff --git a/apps/product/migrations/0020_merge_20191209_0911.py b/apps/product/migrations/0020_merge_20191209_0911.py new file mode 100644 index 00000000..b8c83246 --- /dev/null +++ b/apps/product/migrations/0020_merge_20191209_0911.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.7 on 2019-12-09 09:11 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('product', '0019_auto_20191204_1420'), + ('product', '0019_product_serial_number'), + ] + + operations = [ + ] diff --git a/apps/product/models.py b/apps/product/models.py index 6d3e4954..b125c7eb 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -218,6 +218,10 @@ class Product(GalleryModelMixin, TranslatedFieldsMixin, BaseAttributes, comments = generic.GenericRelation(to='comment.Comment') awards = generic.GenericRelation(to='main.Award', related_query_name='product') + serial_number = models.CharField(max_length=255, + default=None, null=True, + verbose_name=_('Serial number')) + objects = ProductManager.from_queryset(ProductQuerySet)() class Meta: diff --git a/apps/search_indexes/serializers.py b/apps/search_indexes/serializers.py index a43ebaf7..3b5561fa 100644 --- a/apps/search_indexes/serializers.py +++ b/apps/search_indexes/serializers.py @@ -243,8 +243,8 @@ class WineOriginSerializer(serializers.Serializer): class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer): """Establishment document serializer.""" - establishment_type = EstablishmentTypeSerializer() - establishment_subtypes = EstablishmentTypeSerializer(many=True) + type = EstablishmentTypeSerializer(source='establishment_type') + subtypes = EstablishmentTypeSerializer(many=True, source='establishment_subtypes') address = AddressDocumentSerializer(allow_null=True) tags = TagsDocumentSerializer(many=True, source='visible_tags') restaurant_category = TagsDocumentSerializer(many=True, allow_null=True) @@ -280,8 +280,8 @@ class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer): 'wine_origins', # 'works_now', # 'collections', - # 'establishment_type', - # 'establishment_subtypes', + 'type', + 'subtypes', ) diff --git a/apps/transfer/serializers/guide.py b/apps/transfer/serializers/guide.py index f0cddd02..8a083e55 100644 --- a/apps/transfer/serializers/guide.py +++ b/apps/transfer/serializers/guide.py @@ -68,7 +68,7 @@ class GuideSerializer(TransferSerializerMixin): class GuideFilterSerializer(TransferSerializerMixin): id = serializers.IntegerField() year = serializers.CharField(allow_null=True) - establishment_type = serializers.CharField(allow_null=True) + type = serializers.CharField(allow_null=True, source='establishment_type') countries = serializers.CharField(allow_null=True) regions = serializers.CharField(allow_null=True) subregions = serializers.CharField(allow_null=True) @@ -86,7 +86,7 @@ class GuideFilterSerializer(TransferSerializerMixin): fields = ( 'id', 'year', - 'establishment_type', + 'type', 'countries', 'regions', 'subregions', diff --git a/docker-compose.mysql.yml b/docker-compose.mysql.yml index 008acb0b..3dc31d33 100644 --- a/docker-compose.mysql.yml +++ b/docker-compose.mysql.yml @@ -32,6 +32,7 @@ services: - "5436:5432" volumes: - gm-db:/var/lib/postgresql/data/ + - .:/code elasticsearch: