Merge branch 'develop' into migrate/site-affilations
This commit is contained in:
commit
e7deab5bbc
|
|
@ -293,7 +293,9 @@ class User(AbstractUser):
|
||||||
|
|
||||||
class UserRole(ProjectBaseMixin):
|
class UserRole(ProjectBaseMixin):
|
||||||
"""UserRole model."""
|
"""UserRole model."""
|
||||||
user = models.ForeignKey(User, verbose_name=_('User'), on_delete=models.CASCADE)
|
user = models.ForeignKey('account.User',
|
||||||
|
verbose_name=_('User'),
|
||||||
|
on_delete=models.CASCADE)
|
||||||
role = models.ForeignKey(Role, verbose_name=_('Role'), on_delete=models.SET_NULL, null=True)
|
role = models.ForeignKey(Role, verbose_name=_('Role'), on_delete=models.SET_NULL, null=True)
|
||||||
establishment = models.ForeignKey(Establishment, verbose_name=_('Establishment'),
|
establishment = models.ForeignKey(Establishment, verbose_name=_('Establishment'),
|
||||||
on_delete=models.SET_NULL, null=True, blank=True)
|
on_delete=models.SET_NULL, null=True, blank=True)
|
||||||
|
|
|
||||||
|
|
@ -13,15 +13,6 @@ class RoleSerializer(serializers.ModelSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class UserRoleSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = models.UserRole
|
|
||||||
fields = [
|
|
||||||
'user',
|
|
||||||
'role'
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class BackUserSerializer(serializers.ModelSerializer):
|
class BackUserSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
|
|
@ -49,3 +40,13 @@ class BackDetailUserSerializer(BackUserSerializer):
|
||||||
user.set_password(validated_data['password'])
|
user.set_password(validated_data['password'])
|
||||||
user.save()
|
user.save()
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
class UserRoleSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = models.UserRole
|
||||||
|
fields = [
|
||||||
|
'role',
|
||||||
|
'user',
|
||||||
|
'establishment'
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,12 @@ class UserBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
model = models.User
|
model = models.User
|
||||||
fields = (
|
fields = (
|
||||||
|
'id',
|
||||||
|
'username',
|
||||||
'fullname',
|
'fullname',
|
||||||
|
'first_name',
|
||||||
|
'last_name',
|
||||||
|
'email',
|
||||||
'cropped_image_url',
|
'cropped_image_url',
|
||||||
'image_url',
|
'image_url',
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class RoleLstView(generics.ListCreateAPIView):
|
||||||
|
|
||||||
class UserRoleLstView(generics.ListCreateAPIView):
|
class UserRoleLstView(generics.ListCreateAPIView):
|
||||||
serializer_class = serializers.UserRoleSerializer
|
serializer_class = serializers.UserRoleSerializer
|
||||||
queryset = models.Role.objects.all()
|
queryset = models.UserRole.objects.all()
|
||||||
|
|
||||||
|
|
||||||
class UserLstView(generics.ListCreateAPIView):
|
class UserLstView(generics.ListCreateAPIView):
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ class CheckWhetherBookingAvailable(generics.GenericAPIView):
|
||||||
periods = response['periods']
|
periods = response['periods']
|
||||||
periods_by_name = {period['period']: period for period in periods if 'period' in period}
|
periods_by_name = {period['period']: period for period in periods if 'period' in period}
|
||||||
if not periods_by_name:
|
if not periods_by_name:
|
||||||
return None
|
return response
|
||||||
|
|
||||||
period_template = iter(periods_by_name.values()).__next__().copy()
|
period_template = iter(periods_by_name.values()).__next__().copy()
|
||||||
period_template.pop('total_left_seats')
|
period_template.pop('total_left_seats')
|
||||||
|
|
|
||||||
36
apps/establishment/management/commands/fix_scheduler.py
Normal file
36
apps/establishment/management/commands/fix_scheduler.py
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from establishment.models import Establishment
|
||||||
|
from transfer.models import Establishments
|
||||||
|
from transfer.serializers.establishment import EstablishmentSerializer
|
||||||
|
from timetable.models import Timetable
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Fix scheduler'
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
count = 0
|
||||||
|
establishments = Establishment.objects.all()
|
||||||
|
old_est_list = Establishments.objects.prefetch_related(
|
||||||
|
'schedules_set',
|
||||||
|
)
|
||||||
|
# remove old records of Timetable
|
||||||
|
Timetable.objects.all().delete()
|
||||||
|
|
||||||
|
for est in tqdm(establishments, desc="Fix scheduler"):
|
||||||
|
old_est = old_est_list.filter(id=est.old_id).first()
|
||||||
|
|
||||||
|
if old_est and old_est.schedules_set.exists():
|
||||||
|
old_schedule = old_est.schedules_set.first()
|
||||||
|
timetable = old_schedule.timetable
|
||||||
|
if timetable:
|
||||||
|
new_schedules = EstablishmentSerializer.get_schedules(timetable)
|
||||||
|
est.schedule.add(*new_schedules)
|
||||||
|
est.save()
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
self.stdout.write(self.style.WARNING(f'Update {count} objects.'))
|
||||||
|
|
@ -38,7 +38,7 @@ class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView):
|
||||||
.with_extended_address_related().with_currency_related() \
|
.with_extended_address_related().with_currency_related() \
|
||||||
.with_certain_tag_category_related('category', 'restaurant_category') \
|
.with_certain_tag_category_related('category', 'restaurant_category') \
|
||||||
.with_certain_tag_category_related('cuisine', 'restaurant_cuisine') \
|
.with_certain_tag_category_related('cuisine', 'restaurant_cuisine') \
|
||||||
.with_ceratin_tag_category_related('shop_category', 'artisan_category')
|
.with_certain_tag_category_related('shop_category', 'artisan_category')
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,24 @@ class FeatureSerializer(serializers.ModelSerializer):
|
||||||
fields = (
|
fields = (
|
||||||
'id',
|
'id',
|
||||||
'slug',
|
'slug',
|
||||||
'priority'
|
'priority',
|
||||||
|
'route',
|
||||||
|
'site_settings',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class CurrencySerializer(ProjectModelSerializer):
|
||||||
|
"""Currency serializer."""
|
||||||
|
|
||||||
|
name_translated = TranslatedField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = models.Currency
|
||||||
|
fields = [
|
||||||
|
'id',
|
||||||
|
'name_translated',
|
||||||
|
'sign'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class SiteFeatureSerializer(serializers.ModelSerializer):
|
class SiteFeatureSerializer(serializers.ModelSerializer):
|
||||||
id = serializers.IntegerField(source='feature.id')
|
id = serializers.IntegerField(source='feature.id')
|
||||||
|
|
@ -42,20 +57,6 @@ class SiteFeatureSerializer(serializers.ModelSerializer):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CurrencySerializer(ProjectModelSerializer):
|
|
||||||
"""Currency serializer."""
|
|
||||||
|
|
||||||
name_translated = TranslatedField()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = models.Currency
|
|
||||||
fields = [
|
|
||||||
'id',
|
|
||||||
'name_translated',
|
|
||||||
'sign'
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class SiteSettingsSerializer(serializers.ModelSerializer):
|
class SiteSettingsSerializer(serializers.ModelSerializer):
|
||||||
"""Site settings serializer."""
|
"""Site settings serializer."""
|
||||||
|
|
||||||
|
|
@ -99,23 +100,15 @@ class SiteSettingsBackOfficeSerializer(SiteSettingsSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class SiteSerializer(serializers.ModelSerializer):
|
class SiteSerializer(SiteSettingsSerializer):
|
||||||
country = CountrySerializer()
|
country = CountrySerializer()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
model = models.SiteSettings
|
model = models.SiteSettings
|
||||||
fields = [
|
fields = SiteSettingsSerializer.Meta.fields + [
|
||||||
'subdomain',
|
'id',
|
||||||
'site_url',
|
'country'
|
||||||
'country',
|
|
||||||
'default_site',
|
|
||||||
'pinterest_page_url',
|
|
||||||
'twitter_page_url',
|
|
||||||
'facebook_page_url',
|
|
||||||
'instagram_page_url',
|
|
||||||
'contact_email',
|
|
||||||
'currency'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -129,45 +122,6 @@ class SiteShortSerializer(serializers.ModelSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class SiteBackOfficeSerializer(SiteSerializer):
|
|
||||||
"""Serializer for back office."""
|
|
||||||
|
|
||||||
class Meta(SiteSerializer.Meta):
|
|
||||||
"""Meta class."""
|
|
||||||
fields = SiteSerializer.Meta.fields + [
|
|
||||||
'id',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class FeatureSerializer(serializers.ModelSerializer):
|
|
||||||
"""Site feature serializer."""
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Meta class."""
|
|
||||||
|
|
||||||
model = models.Feature
|
|
||||||
fields = (
|
|
||||||
'id',
|
|
||||||
'slug',
|
|
||||||
'priority',
|
|
||||||
'route',
|
|
||||||
'site_settings',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# class SiteFeatureSerializer(serializers.ModelSerializer):
|
|
||||||
# """Site feature serializer."""
|
|
||||||
#
|
|
||||||
# class Meta:
|
|
||||||
# """Meta class."""
|
|
||||||
#
|
|
||||||
# model = models.SiteFeature
|
|
||||||
# fields = (
|
|
||||||
# 'id',
|
|
||||||
# 'published',
|
|
||||||
# 'site_settings',
|
|
||||||
# 'feature',
|
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
class AwardBaseSerializer(serializers.ModelSerializer):
|
class AwardBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
||||||
|
|
@ -13,5 +13,11 @@ urlpatterns = [
|
||||||
path('site-settings/<subdomain>/', views.SiteSettingsBackOfficeView.as_view(),
|
path('site-settings/<subdomain>/', views.SiteSettingsBackOfficeView.as_view(),
|
||||||
name='site-settings'),
|
name='site-settings'),
|
||||||
path('feature/', views.FeatureBackView.as_view(), name='feature-list-create'),
|
path('feature/', views.FeatureBackView.as_view(), name='feature-list-create'),
|
||||||
path('feature/<int:id>/', views.FeatureRUDBackView.as_view(), name='feature-rud')
|
path('feature/<int:id>/', views.FeatureRUDBackView.as_view(), name='feature-rud'),
|
||||||
|
path('site-feature/', views.SiteFeatureBackView.as_view(),
|
||||||
|
name='site-feature-list-create'),
|
||||||
|
path('site-feature/<int:id>/', views.SiteFeatureRUDBackView.as_view(),
|
||||||
|
name='site-feature-rud'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,16 +44,26 @@ class FeatureBackView(generics.ListCreateAPIView):
|
||||||
serializer_class = serializers.FeatureSerializer
|
serializer_class = serializers.FeatureSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class SiteFeatureBackView(generics.ListCreateAPIView):
|
||||||
|
"""Feature list or create View."""
|
||||||
|
serializer_class = serializers.SiteFeatureSerializer
|
||||||
|
|
||||||
|
|
||||||
class FeatureRUDBackView(generics.RetrieveUpdateDestroyAPIView):
|
class FeatureRUDBackView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
"""Feature RUD View."""
|
"""Feature RUD View."""
|
||||||
serializer_class = serializers.FeatureSerializer
|
serializer_class = serializers.FeatureSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class SiteFeatureRUDBackView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
|
"""Feature RUD View."""
|
||||||
|
serializer_class = serializers.SiteFeatureSerializer
|
||||||
|
|
||||||
|
|
||||||
class SiteSettingsBackOfficeView(SiteSettingsView):
|
class SiteSettingsBackOfficeView(SiteSettingsView):
|
||||||
"""Site settings View."""
|
"""Site settings View."""
|
||||||
serializer_class = serializers.SiteSettingsBackOfficeSerializer
|
serializer_class = serializers.SiteSerializer
|
||||||
|
|
||||||
|
|
||||||
class SiteListBackOfficeView(SiteListView):
|
class SiteListBackOfficeView(SiteListView):
|
||||||
"""Site settings View."""
|
"""Site settings View."""
|
||||||
serializer_class = serializers.SiteBackOfficeSerializer
|
serializer_class = serializers.SiteSerializer
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from search_indexes.documents.establishment import EstablishmentDocument
|
from search_indexes.documents.establishment import EstablishmentDocument
|
||||||
from search_indexes.documents.news import NewsDocument
|
from search_indexes.documents.news import NewsDocument
|
||||||
from search_indexes.documents.product import ProductDocument
|
from search_indexes.documents.product import ProductDocument
|
||||||
|
from search_indexes.documents.tag_category import TagCategoryDocument
|
||||||
from search_indexes.tasks import es_update
|
from search_indexes.tasks import es_update
|
||||||
|
|
||||||
# todo: make signal to update documents on related fields
|
# todo: make signal to update documents on related fields
|
||||||
|
|
@ -8,5 +9,6 @@ __all__ = [
|
||||||
'EstablishmentDocument',
|
'EstablishmentDocument',
|
||||||
'NewsDocument',
|
'NewsDocument',
|
||||||
'ProductDocument',
|
'ProductDocument',
|
||||||
|
'TagCategoryDocument',
|
||||||
'es_update',
|
'es_update',
|
||||||
]
|
]
|
||||||
33
apps/search_indexes/documents/tag_category.py
Normal file
33
apps/search_indexes/documents/tag_category.py
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
"""Product app documents."""
|
||||||
|
from django.conf import settings
|
||||||
|
from django_elasticsearch_dsl import Document, Index, fields
|
||||||
|
from tag import models
|
||||||
|
|
||||||
|
TagCategoryIndex = Index(settings.ELASTICSEARCH_INDEX_NAMES.get(__name__, 'tag_category'))
|
||||||
|
TagCategoryIndex.settings(number_of_shards=2, number_of_replicas=2)
|
||||||
|
|
||||||
|
|
||||||
|
@TagCategoryIndex.doc_type
|
||||||
|
class TagCategoryDocument(Document):
|
||||||
|
"""TagCategory document."""
|
||||||
|
|
||||||
|
tags = fields.ListField(fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'id': fields.IntegerField(),
|
||||||
|
'value': fields.KeywordField(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
|
||||||
|
class Django:
|
||||||
|
model = models.TagCategory
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'index_name',
|
||||||
|
'public',
|
||||||
|
'value_type'
|
||||||
|
)
|
||||||
|
related_models = [models.Tag]
|
||||||
|
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return super().get_queryset().with_base_related()
|
||||||
|
|
@ -4,6 +4,8 @@ from django_elasticsearch_dsl_drf.filter_backends import SearchFilterBackend, \
|
||||||
FacetedSearchFilterBackend, GeoSpatialFilteringFilterBackend
|
FacetedSearchFilterBackend, GeoSpatialFilteringFilterBackend
|
||||||
from search_indexes.utils import OBJECT_FIELD_PROPERTIES
|
from search_indexes.utils import OBJECT_FIELD_PROPERTIES
|
||||||
from six import iteritems
|
from six import iteritems
|
||||||
|
from search_indexes.documents import TagCategoryDocument
|
||||||
|
from tag.models import TagCategory
|
||||||
|
|
||||||
|
|
||||||
class CustomGeoSpatialFilteringFilterBackend(GeoSpatialFilteringFilterBackend):
|
class CustomGeoSpatialFilteringFilterBackend(GeoSpatialFilteringFilterBackend):
|
||||||
|
|
@ -11,7 +13,7 @@ class CustomGeoSpatialFilteringFilterBackend(GeoSpatialFilteringFilterBackend):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calculate_center(first, second):
|
def calculate_center(first, second):
|
||||||
if second[1] < 0 <= first[1]:
|
if second[1] < 0 < first[1]:
|
||||||
reverse_first, reverse_second = 180 - abs(first[1]), 180 - abs(second[1])
|
reverse_first, reverse_second = 180 - abs(first[1]), 180 - abs(second[1])
|
||||||
diff = (reverse_first + reverse_second) / 2
|
diff = (reverse_first + reverse_second) / 2
|
||||||
|
|
||||||
|
|
@ -21,6 +23,10 @@ class CustomGeoSpatialFilteringFilterBackend(GeoSpatialFilteringFilterBackend):
|
||||||
else:
|
else:
|
||||||
result_part = 180 - (180 - first[1] - diff)
|
result_part = 180 - (180 - first[1] - diff)
|
||||||
|
|
||||||
|
elif second[1] < 0 > first[1] or second[1] > 0 < first[1]:
|
||||||
|
reverse_first, reverse_second = 180 - abs(first[1]), 180 - abs(second[1])
|
||||||
|
result_part = ((reverse_first + reverse_second) / 2) * (-1 + (second[1] < 0) * 2)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
result_part = (first[1] + second[1]) / 2
|
result_part = (first[1] + second[1]) / 2
|
||||||
|
|
||||||
|
|
@ -52,10 +58,30 @@ class CustomFacetedSearchFilterBackend(FacetedSearchFilterBackend):
|
||||||
:param view:
|
:param view:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
def makefilter(cur_facet):
|
def make_filter(cur_facet):
|
||||||
def myfilter(x):
|
def _filter(x):
|
||||||
return cur_facet['facet']._params['field'] != next(iter(x._params))
|
return cur_facet['facet']._params['field'] != next(iter(x._params))
|
||||||
return myfilter
|
return _filter
|
||||||
|
|
||||||
|
def make_tags_filter(cur_facet, tags_to_remove_ids):
|
||||||
|
def _filter(x):
|
||||||
|
if hasattr(x, '_params') and (x._params.get('must') or x._params.get('should')):
|
||||||
|
ret = []
|
||||||
|
for t in ['must', 'should']:
|
||||||
|
terms = x._params.get(t)
|
||||||
|
if terms:
|
||||||
|
for term in terms:
|
||||||
|
if cur_facet['facet']._params['field'] != next(iter(term._params)):
|
||||||
|
return True # different fields. preserve filter
|
||||||
|
else:
|
||||||
|
ret.append(next(iter(term._params.values())) not in tags_to_remove_ids)
|
||||||
|
return all(ret)
|
||||||
|
if cur_facet['facet']._params['field'] != next(iter(x._params)):
|
||||||
|
return True # different fields. preserve filter
|
||||||
|
else:
|
||||||
|
return next(iter(x._params.values())) not in tags_to_remove_ids
|
||||||
|
return _filter
|
||||||
|
|
||||||
__facets = self.construct_facets(request, view)
|
__facets = self.construct_facets(request, view)
|
||||||
setattr(view.paginator, 'facets_computed', {})
|
setattr(view.paginator, 'facets_computed', {})
|
||||||
for __field, __facet in iteritems(__facets):
|
for __field, __facet in iteritems(__facets):
|
||||||
|
|
@ -67,29 +93,73 @@ class CustomFacetedSearchFilterBackend(FacetedSearchFilterBackend):
|
||||||
'global'
|
'global'
|
||||||
).bucket(__field, agg)
|
).bucket(__field, agg)
|
||||||
else:
|
else:
|
||||||
qs = queryset.__copy__()
|
if __field != 'tag':
|
||||||
qs.query = queryset.query._clone()
|
qs = queryset.__copy__()
|
||||||
filterer = makefilter(__facet)
|
qs.query = queryset.query._clone()
|
||||||
for param_type in ['must', 'must_not', 'should']:
|
filterer = make_filter(__facet)
|
||||||
if qs.query._proxied._params.get(param_type):
|
for param_type in ['must', 'must_not', 'should']:
|
||||||
qs.query._proxied._params[param_type] = list(
|
if qs.query._proxied._params.get(param_type):
|
||||||
filter(
|
qs.query._proxied._params[param_type] = list(
|
||||||
filterer, qs.query._proxied._params[param_type]
|
filter(
|
||||||
|
filterer, qs.query._proxied._params[param_type]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
sh = qs.query._proxied._params.get('should')
|
||||||
sh = qs.query._proxied._params.get('should')
|
if (not sh or not len(sh)) \
|
||||||
if (not sh or not len(sh)) \
|
and qs.query._proxied._params.get('minimum_should_match'):
|
||||||
and qs.query._proxied._params.get('minimum_should_match'):
|
qs.query._proxied._params.pop('minimum_should_match')
|
||||||
qs.query._proxied._params.pop('minimum_should_match')
|
facet_name = '_filter_' + __field
|
||||||
facet_name = '_filter_' + __field
|
qs.aggs.bucket(
|
||||||
qs.aggs.bucket(
|
facet_name,
|
||||||
facet_name,
|
'filter',
|
||||||
'filter',
|
filter=agg_filter
|
||||||
filter=agg_filter
|
).bucket(__field, agg)
|
||||||
).bucket(__field, agg)
|
view.paginator.facets_computed.update({facet_name: qs.execute().aggregations[facet_name]})
|
||||||
view.paginator.facets_computed.update({facet_name: qs.execute().aggregations[facet_name]})
|
else:
|
||||||
|
tag_facets = []
|
||||||
|
preserve_ids = []
|
||||||
|
facet_name = '_filter_' + __field
|
||||||
|
all_tag_categories = TagCategoryDocument.search() \
|
||||||
|
.filter('term', public=True) \
|
||||||
|
.filter(Q('term', value_type=TagCategory.LIST) | Q('match', index_name='wine-color'))
|
||||||
|
for category in all_tag_categories:
|
||||||
|
tags_to_remove = list(map(lambda t: str(t.id), category.tags))
|
||||||
|
qs = queryset.__copy__()
|
||||||
|
qs.query = queryset.query._clone()
|
||||||
|
filterer = make_tags_filter(__facet, tags_to_remove)
|
||||||
|
for param_type in ['must', 'should']:
|
||||||
|
if qs.query._proxied._params.get(param_type):
|
||||||
|
if qs.query._proxied._params.get(param_type):
|
||||||
|
qs.query._proxied._params[param_type] = list(
|
||||||
|
filter(
|
||||||
|
filterer, qs.query._proxied._params[param_type]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
sh = qs.query._proxied._params.get('should')
|
||||||
|
if (not sh or not len(sh)) \
|
||||||
|
and qs.query._proxied._params.get('minimum_should_match'):
|
||||||
|
qs.query._proxied._params.pop('minimum_should_match')
|
||||||
|
qs.aggs.bucket(
|
||||||
|
facet_name,
|
||||||
|
'filter',
|
||||||
|
filter=agg_filter
|
||||||
|
).bucket(__field, agg)
|
||||||
|
tag_facets.append(qs.execute().aggregations[facet_name])
|
||||||
|
preserve_ids.append(list(map(int, tags_to_remove)))
|
||||||
|
view.paginator.facets_computed.update({facet_name: self.merge_buckets(tag_facets, preserve_ids)})
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def merge_buckets(buckets: list, preserve_ids: list):
|
||||||
|
"""Reduces all buckets preserving class"""
|
||||||
|
result_bucket = buckets[0]
|
||||||
|
result_bucket.tag.buckets = list(filter(lambda x: x['key'] in preserve_ids[0], result_bucket.tag.buckets._l_))
|
||||||
|
for bucket, ids in list(zip(buckets, preserve_ids))[1:]:
|
||||||
|
for tag in bucket.tag.buckets._l_:
|
||||||
|
if tag['key'] in ids:
|
||||||
|
result_bucket.tag.buckets.append(tag)
|
||||||
|
return result_bucket
|
||||||
|
|
||||||
|
|
||||||
class CustomSearchFilterBackend(SearchFilterBackend):
|
class CustomSearchFilterBackend(SearchFilterBackend):
|
||||||
"""Custom SearchFilterBackend."""
|
"""Custom SearchFilterBackend."""
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,10 @@ class TagsFilterSet(TagsBaseFilterSet):
|
||||||
|
|
||||||
def by_establishment_type(self, queryset, name, value):
|
def by_establishment_type(self, queryset, name, value):
|
||||||
if value == EstablishmentType.ARTISAN:
|
if value == EstablishmentType.ARTISAN:
|
||||||
return models.Tag.objects.by_category_index_name('shop_category')[0:8]
|
qs = models.Tag.objects.by_category_index_name('shop_category')
|
||||||
|
if self.request.country_code and self.request.country_code not in settings.INTERNATIONAL_COUNTRY_CODES:
|
||||||
|
qs = qs.filter(establishments__address__city__country__code=self.request.country_code).distinct('id')
|
||||||
|
return qs.exclude(establishments__isnull=True)[0:8]
|
||||||
return queryset.by_establishment_type(value)
|
return queryset.by_establishment_type(value)
|
||||||
|
|
||||||
# TMP TODO remove it later
|
# TMP TODO remove it later
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ class EstablishmentSerializer(serializers.ModelSerializer):
|
||||||
weekdays = {
|
weekdays = {
|
||||||
'su': Timetable.SUNDAY,
|
'su': Timetable.SUNDAY,
|
||||||
'mo': Timetable.MONDAY,
|
'mo': Timetable.MONDAY,
|
||||||
'tu': Timetable.THURSDAY,
|
'tu': Timetable.TUESDAY,
|
||||||
'we': Timetable.WEDNESDAY,
|
'we': Timetable.WEDNESDAY,
|
||||||
'th': Timetable.THURSDAY,
|
'th': Timetable.THURSDAY,
|
||||||
'fr': Timetable.FRIDAY,
|
'fr': Timetable.FRIDAY,
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ ELASTICSEARCH_INDEX_NAMES = {
|
||||||
'search_indexes.documents.news': 'development_news',
|
'search_indexes.documents.news': 'development_news',
|
||||||
'search_indexes.documents.establishment': 'development_establishment',
|
'search_indexes.documents.establishment': 'development_establishment',
|
||||||
'search_indexes.documents.product': 'development_product',
|
'search_indexes.documents.product': 'development_product',
|
||||||
|
'search_indexes.documents.tag_category': 'development_tag_category',
|
||||||
}
|
}
|
||||||
|
|
||||||
# ELASTICSEARCH_DSL_AUTOSYNC = False
|
# ELASTICSEARCH_DSL_AUTOSYNC = False
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ ELASTICSEARCH_INDEX_NAMES = {
|
||||||
# 'search_indexes.documents.news': 'local_news',
|
# 'search_indexes.documents.news': 'local_news',
|
||||||
'search_indexes.documents.establishment': 'local_establishment',
|
'search_indexes.documents.establishment': 'local_establishment',
|
||||||
'search_indexes.documents.product': 'local_product',
|
'search_indexes.documents.product': 'local_product',
|
||||||
|
'search_indexes.documents.tag_category': 'local_tag_category',
|
||||||
}
|
}
|
||||||
ELASTICSEARCH_DSL_AUTOSYNC = False
|
ELASTICSEARCH_DSL_AUTOSYNC = False
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ ELASTICSEARCH_INDEX_NAMES = {
|
||||||
'search_indexes.documents.news': 'development_news', # temporarily disabled
|
'search_indexes.documents.news': 'development_news', # temporarily disabled
|
||||||
'search_indexes.documents.establishment': 'development_establishment',
|
'search_indexes.documents.establishment': 'development_establishment',
|
||||||
'search_indexes.documents.product': 'development_product',
|
'search_indexes.documents.product': 'development_product',
|
||||||
|
'search_indexes.documents.tag_category': 'development_tag_category',
|
||||||
}
|
}
|
||||||
|
|
||||||
sentry_sdk.init(
|
sentry_sdk.init(
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ ELASTICSEARCH_DSL = {
|
||||||
ELASTICSEARCH_INDEX_NAMES = {
|
ELASTICSEARCH_INDEX_NAMES = {
|
||||||
# 'search_indexes.documents.news': 'stage_news', #temporarily disabled
|
# 'search_indexes.documents.news': 'stage_news', #temporarily disabled
|
||||||
'search_indexes.documents.establishment': 'stage_establishment',
|
'search_indexes.documents.establishment': 'stage_establishment',
|
||||||
|
'search_indexes.documents.tag_category': 'stage_tag_category',
|
||||||
}
|
}
|
||||||
|
|
||||||
COOKIE_DOMAIN = '.id-east.ru'
|
COOKIE_DOMAIN = '.id-east.ru'
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user