From 6cbfc38c9c159dde2c48b7278ac3dd3a3b1c1139 Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 17:58:39 +0300 Subject: [PATCH 01/28] Added back collections method for collection detail --- apps/collection/urls/back.py | 8 +++++++- apps/collection/views/back.py | 10 ++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/apps/collection/urls/back.py b/apps/collection/urls/back.py index 6a6dbd54..d7f77b9a 100644 --- a/apps/collection/urls/back.py +++ b/apps/collection/urls/back.py @@ -1,4 +1,5 @@ """Collection common urlpaths.""" +from django.urls import path from rest_framework.routers import SimpleRouter from collection.views import back as views @@ -7,4 +8,9 @@ app_name = 'collection' router = SimpleRouter() router.register(r'', views.CollectionBackOfficeViewSet) -urlpatterns = router.urls +urlpatterns = [ + path('//', views.CollectionBackOfficeView.as_view(), name='detail'), +] + +urlpatterns += router.urls + diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index a989ec56..65bd6c8b 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,3 +1,4 @@ +from rest_framework import generics from rest_framework import permissions from rest_framework import viewsets, mixins @@ -47,3 +48,12 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, collection.establishments.remove(related_object) elif obj_type == self.bind_object_serializer_class.PRODUCT: collection.products.remove(related_object) + + +class CollectionBackOfficeView(generics.GenericAPIView): + """ViewS for Collection model.""" + + pagination_class = None + permission_classes = (permissions.IsAuthenticated,) + queryset = models.Collection.objects.all() + serializer_class = serializers.CollectionBackOfficeSerializer From a6b77e74b541546c9f7a09e2fc8f7e519f8bdd16 Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 17:59:42 +0300 Subject: [PATCH 02/28] Remove unnecessary slash --- apps/collection/urls/back.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/collection/urls/back.py b/apps/collection/urls/back.py index d7f77b9a..f97a3945 100644 --- a/apps/collection/urls/back.py +++ b/apps/collection/urls/back.py @@ -9,7 +9,7 @@ router = SimpleRouter() router.register(r'', views.CollectionBackOfficeViewSet) urlpatterns = [ - path('//', views.CollectionBackOfficeView.as_view(), name='detail'), + path('/', views.CollectionBackOfficeView.as_view(), name='detail'), ] urlpatterns += router.urls From e0a66f300b76f8d60531f070aeb06c9b50c4cfb4 Mon Sep 17 00:00:00 2001 From: dormantman Date: Wed, 11 Dec 2019 18:07:04 +0300 Subject: [PATCH 03/28] Hide unnecessary fields --- apps/collection/serializers/back.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index 48c25f6c..6cedb087 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -33,11 +33,11 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): 'on_top', 'country', 'country_id', - 'block_size', - 'description', + # 'block_size', + # 'description', 'slug', - 'start', - 'end', + # 'start', + # 'end', 'count_related_objects', 'related_object_names', ] From d2f011417afb38acdfc5deaf5e18f8c9d8831254 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Wed, 11 Dec 2019 18:11:39 +0300 Subject: [PATCH 04/28] add datamigrate and change for models --- apps/account/management/commands/add_ownership.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/account/management/commands/add_ownership.py diff --git a/apps/account/management/commands/add_ownership.py b/apps/account/management/commands/add_ownership.py new file mode 100644 index 00000000..e69de29b From 86b2e708f05162c0791fbc81c40eae3c060d5980 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Wed, 11 Dec 2019 18:12:26 +0300 Subject: [PATCH 05/28] add datamigrate and change for models --- .../management/commands/add_ownership.py | 49 +++++++++++++++ .../migrations/0026_auto_20191211_1134.py | 25 ++++++++ .../migrations/0027_auto_20191211_1444.py | 18 ++++++ apps/account/models.py | 59 ++++++++++++++----- apps/account/serializers/back.py | 4 ++ apps/account/urls/back.py | 1 + apps/account/views/back.py | 6 ++ apps/transfer/models.py | 16 +++++ 8 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 apps/account/migrations/0026_auto_20191211_1134.py create mode 100644 apps/account/migrations/0027_auto_20191211_1444.py diff --git a/apps/account/management/commands/add_ownership.py b/apps/account/management/commands/add_ownership.py index e69de29b..84926d9c 100644 --- a/apps/account/management/commands/add_ownership.py +++ b/apps/account/management/commands/add_ownership.py @@ -0,0 +1,49 @@ +from django.core.management.base import BaseCommand +from tqdm import tqdm + +from account.models import User, UserRole, Role +from transfer.models import OwnershipAffs +from establishment.models import Establishment + + +class Command(BaseCommand): + help = """Add ownership to UserRoles.""" + + def handle(self, *args, **kwarg): + create_user_roles = [] + # filter owner records with state not null only + owners = OwnershipAffs.objects.filter(state__isnull=False) + + # Get role, may be more then 1 + role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER).first() + if not role: + role = Role.objects.create( + role=Role.ESTABLISHMENT_MANAGER + ) + + for owner in tqdm(owners): + user = User.objects.filter( + old_id=owner.account_id).first() + requester = User.objects.filter( + old_id=owner.requester_id).first() + establishment = Establishment.objects.filter( + old_id=owner.establishment_id).first() + + if user and establishment: + user_role = UserRole.objects.filter( + user=user, role=role, establishment=establishment, state=owner.state).first() + if not user_role: + # add to bulk_create + create_user_roles.append(UserRole( + user=user, + role=role, + establishment=establishment, + state=owner.state, + requester=requester + )) + + UserRole.objects.bulk_create(create_user_roles) + self.stdout.write( + self.style.WARNING( + f'Created roles: {len(create_user_roles)}') + ) diff --git a/apps/account/migrations/0026_auto_20191211_1134.py b/apps/account/migrations/0026_auto_20191211_1134.py new file mode 100644 index 00000000..7325c9a7 --- /dev/null +++ b/apps/account/migrations/0026_auto_20191211_1134.py @@ -0,0 +1,25 @@ +# Generated by Django 2.2.7 on 2019-12-11 11:34 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0025_auto_20191210_0623'), + ] + + operations = [ + migrations.AddField( + model_name='userrole', + name='requester', + field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='roles_requested', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='userrole', + name='state', + field=models.CharField(choices=[('validated', 'validated'), ('pending', 'pending'), ('cancelled', 'cancelled'), ('rejected', 'rejected')], default='pending', max_length=10, verbose_name='state'), + ), + ] diff --git a/apps/account/migrations/0027_auto_20191211_1444.py b/apps/account/migrations/0027_auto_20191211_1444.py new file mode 100644 index 00000000..ed0886e7 --- /dev/null +++ b/apps/account/migrations/0027_auto_20191211_1444.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.7 on 2019-12-11 14:44 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0067_auto_20191122_1244'), + ('account', '0026_auto_20191211_1134'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='userrole', + unique_together={('user', 'role', 'establishment', 'state')}, + ), + ] diff --git a/apps/account/models.py b/apps/account/models.py index 70a3cd69..b4744bd6 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -34,16 +34,16 @@ class Role(ProjectBaseMixin): REVIEWER_MANGER = 6 RESTAURANT_REVIEWER = 7 SALES_MAN = 8 - WINERY_REVIEWER = 9 # Establishments subtype "winery" + WINERY_REVIEWER = 9 # Establishments subtype "winery" SELLER = 10 ROLE_CHOICES = ( - (STANDARD_USER, 'Standard user'), - (COMMENTS_MODERATOR, 'Comments moderator'), - (COUNTRY_ADMIN, 'Country admin'), - (CONTENT_PAGE_MANAGER, 'Content page manager'), - (ESTABLISHMENT_MANAGER, 'Establishment manager'), - (REVIEWER_MANGER, 'Reviewer manager'), + (STANDARD_USER, _('Standard user')), + (COMMENTS_MODERATOR, _('Comments moderator')), + (COUNTRY_ADMIN, _('Country admin')), + (CONTENT_PAGE_MANAGER, _('Content page manager')), + (ESTABLISHMENT_MANAGER, _('Establishment manager')), + (REVIEWER_MANGER, _('Reviewer manager')), (RESTAURANT_REVIEWER, 'Restaurant reviewer'), (SALES_MAN, 'Sales man'), (WINERY_REVIEWER, 'Winery reviewer'), @@ -93,6 +93,14 @@ class UserQuerySet(models.QuerySet): return self.filter(oauth2_provider_refreshtoken__token=token, oauth2_provider_refreshtoken__expires__gt=timezone.now()) + def by_role(self, role): + """Filter by role.""" + return self.filter(userrole__role=role).dictinct() + + def by_roles(self, roles: list): + """Filter by roles.""" + return self.filter(userrole__role__in=roles).dictinct() + class User(AbstractUser): """Base user model.""" @@ -116,7 +124,9 @@ class User(AbstractUser): USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] - roles = models.ManyToManyField(Role, verbose_name=_('Roles'), through='UserRole') + roles = models.ManyToManyField( + Role, verbose_name=_('Roles'), symmetrical=False, + through_fields=('user', 'role'), through='UserRole') objects = UserManager.from_queryset(UserQuerySet)() class Meta: @@ -301,14 +311,33 @@ class User(AbstractUser): class UserRole(ProjectBaseMixin): """UserRole model.""" - 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) - establishment = models.ForeignKey(Establishment, verbose_name=_('Establishment'), - on_delete=models.SET_NULL, null=True, blank=True) + VALIDATED = 'validated' + PENDING = 'pending' + CANCELLED = 'cancelled' + REJECTED = 'rejected' + + STATE_CHOICES = ( + (VALIDATED, _('validated')), + (PENDING, _('pending')), + (CANCELLED, _('cancelled')), + (REJECTED, _('rejected')) + ) + 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) + establishment = models.ForeignKey( + Establishment, verbose_name=_('Establishment'), + on_delete=models.SET_NULL, null=True, blank=True) + + state = models.CharField( + _('state'), choices=STATE_CHOICES, max_length=10, default=PENDING) + requester = models.ForeignKey( + 'account.User', blank=True, null=True, default=None, related_name='roles_requested', + on_delete=models.SET_NULL) + class Meta: - unique_together = ['user', 'role'] + unique_together = ['user', 'role', 'establishment', 'state'] class OldRole(models.Model): diff --git a/apps/account/serializers/back.py b/apps/account/serializers/back.py index 01889411..1ee6a8b1 100644 --- a/apps/account/serializers/back.py +++ b/apps/account/serializers/back.py @@ -70,3 +70,7 @@ class UserRoleSerializer(serializers.ModelSerializer): 'user', 'establishment' ] + + +class OwnerSerializer(BackUserSerializer): + """Owner serializer.""" diff --git a/apps/account/urls/back.py b/apps/account/urls/back.py index 30f21573..5c87e525 100644 --- a/apps/account/urls/back.py +++ b/apps/account/urls/back.py @@ -10,4 +10,5 @@ urlpatterns = [ path('user-role/', views.UserRoleLstView.as_view(), name='user-role-list-create'), path('user/', views.UserLstView.as_view(), name='user-create-list'), path('user//', views.UserRUDView.as_view(), name='user-rud'), + path('owner/', views.OwnerListView.as_view(), name='owner-list'), ] diff --git a/apps/account/views/back.py b/apps/account/views/back.py index fbbc986e..08d3713d 100644 --- a/apps/account/views/back.py +++ b/apps/account/views/back.py @@ -46,3 +46,9 @@ class UserRUDView(generics.RetrieveUpdateDestroyAPIView): serializer_class = serializers.BackDetailUserSerializer permission_classes = (permissions.IsAdminUser,) lookup_field = 'id' + + +class OwnerListView(generics.ListAPIView): + serializer_class = serializers.OwnerSerializer + queryset = models.User.objects.active() + permission_classes = (permissions.IsAuthenticatedOrReadOnly, ) diff --git a/apps/transfer/models.py b/apps/transfer/models.py index d8268d6d..4f2c7ba9 100644 --- a/apps/transfer/models.py +++ b/apps/transfer/models.py @@ -1222,3 +1222,19 @@ class Footers(MigrateMixin): class Meta: managed = False db_table = 'footers' + + +class OwnershipAffs(MigrateMixin): + using = 'legacy' + + role = models.CharField(max_length=255, blank=True, null=True) + state = models.CharField(max_length=255, blank=True, null=True) + account_id = models.IntegerField(blank=True, null=True) + establishment_id = models.IntegerField(blank=True, null=True) + created_at = models.DateTimeField() + updated_at = models.DateTimeField() + requester_id = models.IntegerField(blank=True, null=True) + + class Meta: + managed = False + db_table = 'ownership_affs' \ No newline at end of file From 450ca4cf52aa105a082c1817756b65ebf31b057f Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 03:50:12 +0300 Subject: [PATCH 06/28] Added new field rank to collection --- apps/collection/models.py | 2 ++ apps/collection/serializers/back.py | 13 +++++++------ apps/collection/views/back.py | 8 +++++++- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index 7acd9991..14bd99c0 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -80,6 +80,8 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, verbose_name=_('Collection slug'), editable=True, null=True) old_id = models.IntegerField(null=True, blank=True) + rank = models.IntegerField(null=True, default=None) + objects = CollectionQuerySet.as_manager() class Meta: diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index 6cedb087..f41e3875 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -40,6 +40,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): # 'end', 'count_related_objects', 'related_object_names', + 'rank', ] @@ -68,15 +69,15 @@ class CollectionBindObjectSerializer(serializers.Serializer): attrs['collection'] = collection if obj_type == self.ESTABLISHMENT: - establishment = Establishment.objects.filter(pk=obj_id).\ + establishment = Establishment.objects.filter(pk=obj_id). \ first() if not establishment: raise BindingObjectNotFound() - if request.method == 'POST' and collection.establishments.\ + if request.method == 'POST' and collection.establishments. \ filter(pk=establishment.pk).exists(): raise ObjectAlreadyAdded() - if request.method == 'DELETE' and not collection.\ - establishments.filter(pk=establishment.pk).\ + if request.method == 'DELETE' and not collection. \ + establishments.filter(pk=establishment.pk). \ exists(): raise RemovedBindingObjectNotFound() attrs['related_object'] = establishment @@ -84,10 +85,10 @@ class CollectionBindObjectSerializer(serializers.Serializer): product = Product.objects.filter(pk=obj_id).first() if not product: raise BindingObjectNotFound() - if request.method == 'POST' and collection.products.\ + if request.method == 'POST' and collection.products. \ filter(pk=product.pk).exists(): raise ObjectAlreadyAdded() - if request.method == 'DELETE' and not collection.products.\ + if request.method == 'DELETE' and not collection.products. \ filter(pk=product.pk).exists(): raise RemovedBindingObjectNotFound() attrs['related_object'] = product diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index 65bd6c8b..67548c83 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,6 +1,7 @@ from rest_framework import generics from rest_framework import permissions -from rest_framework import viewsets, mixins +from rest_framework import viewsets +from rest_framework.response import Response from collection import models from collection.serializers import back as serializers @@ -49,6 +50,11 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, elif obj_type == self.bind_object_serializer_class.PRODUCT: collection.products.remove(related_object) + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()).order_by('rank', '-start') + serializer = self.get_serializer(queryset, many=True) + return Response(serializer.data) + class CollectionBackOfficeView(generics.GenericAPIView): """ViewS for Collection model.""" From 5c171c644cbc99a6905cbe0840b95f8c7416dd6f Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 03:52:52 +0300 Subject: [PATCH 07/28] Added mixins --- apps/collection/views/back.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index 67548c83..fdb441c2 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,4 +1,5 @@ from rest_framework import generics +from rest_framework import mixins from rest_framework import permissions from rest_framework import viewsets from rest_framework.response import Response From bd6f8a47a1aa00fb99ce3e4da73c92d839209af9 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Fri, 13 Dec 2019 11:02:37 +0300 Subject: [PATCH 08/28] add api for establishment admin --- apps/account/models.py | 8 ++++++-- apps/account/serializers/back.py | 4 ---- apps/account/urls/back.py | 1 - apps/account/views/back.py | 6 ------ apps/establishment/serializers/back.py | 11 +++++++++++ apps/establishment/urls/back.py | 2 ++ apps/establishment/views/back.py | 19 +++++++++++++++---- 7 files changed, 34 insertions(+), 17 deletions(-) diff --git a/apps/account/models.py b/apps/account/models.py index b4744bd6..b48a419c 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -95,11 +95,15 @@ class UserQuerySet(models.QuerySet): def by_role(self, role): """Filter by role.""" - return self.filter(userrole__role=role).dictinct() + return self.filter(userrole__role=role) def by_roles(self, roles: list): """Filter by roles.""" - return self.filter(userrole__role__in=roles).dictinct() + return self.filter(userrole__role__in=roles) + + def establishment_admin(self, establishment): + role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER).first() + return self.by_role(role).filter(userrole__establishment=establishment) class User(AbstractUser): diff --git a/apps/account/serializers/back.py b/apps/account/serializers/back.py index 1ee6a8b1..01889411 100644 --- a/apps/account/serializers/back.py +++ b/apps/account/serializers/back.py @@ -70,7 +70,3 @@ class UserRoleSerializer(serializers.ModelSerializer): 'user', 'establishment' ] - - -class OwnerSerializer(BackUserSerializer): - """Owner serializer.""" diff --git a/apps/account/urls/back.py b/apps/account/urls/back.py index 5c87e525..30f21573 100644 --- a/apps/account/urls/back.py +++ b/apps/account/urls/back.py @@ -10,5 +10,4 @@ urlpatterns = [ path('user-role/', views.UserRoleLstView.as_view(), name='user-role-list-create'), path('user/', views.UserLstView.as_view(), name='user-create-list'), path('user//', views.UserRUDView.as_view(), name='user-rud'), - path('owner/', views.OwnerListView.as_view(), name='owner-list'), ] diff --git a/apps/account/views/back.py b/apps/account/views/back.py index 08d3713d..fbbc986e 100644 --- a/apps/account/views/back.py +++ b/apps/account/views/back.py @@ -46,9 +46,3 @@ class UserRUDView(generics.RetrieveUpdateDestroyAPIView): serializer_class = serializers.BackDetailUserSerializer permission_classes = (permissions.IsAdminUser,) lookup_field = 'id' - - -class OwnerListView(generics.ListAPIView): - serializer_class = serializers.OwnerSerializer - queryset = models.User.objects.active() - permission_classes = (permissions.IsAuthenticatedOrReadOnly, ) diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py index a1b6cc4a..b7d429da 100644 --- a/apps/establishment/serializers/back.py +++ b/apps/establishment/serializers/back.py @@ -324,3 +324,14 @@ class EstablishmentNoteListCreateSerializer(EstablishmentNoteBaseSerializer): """Return establishment instance from view.""" if self.serializer_view: return self.serializer_view.get_object() + + +class EstablishmentAdminListSerializer(UserShortSerializer): + """Establishment admin serializer.""" + class Meta: + model = UserShortSerializer.Meta.model + fields = [ + 'id', + 'username', + 'email' + ] diff --git a/apps/establishment/urls/back.py b/apps/establishment/urls/back.py index ce1c7b27..b2a30917 100644 --- a/apps/establishment/urls/back.py +++ b/apps/establishment/urls/back.py @@ -28,6 +28,8 @@ urlpatterns = [ name='note-list-create'), path('slug//notes//', views.EstablishmentNoteRUDView.as_view(), name='note-rud'), + path('slug//admin/', views.EstablishmentAdminView.as_view(), + name='establishment-admin-list'), path('menus/', views.MenuListCreateView.as_view(), name='menu-list'), path('menus//', views.MenuRUDView.as_view(), name='menu-rud'), path('plates/', views.PlateListCreateView.as_view(), name='plates'), diff --git a/apps/establishment/views/back.py b/apps/establishment/views/back.py index 6e2c953a..91d40422 100644 --- a/apps/establishment/views/back.py +++ b/apps/establishment/views/back.py @@ -1,15 +1,15 @@ """Establishment app views.""" from django.http import Http404, HttpResponse from django.shortcuts import get_object_or_404 -from rest_framework import generics, permissions, status +from rest_framework import generics, permissions +from rest_framework import status +from account.models import User from establishment import filters, models, serializers +from timetable.models import Timetable from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer from utils.permissions import IsCountryAdmin, IsEstablishmentManager, IsWineryReviewer from utils.views import CreateDestroyGalleryViewMixin -from timetable.models import Timetable -from rest_framework import status -from rest_framework.response import Response class EstablishmentMixinViews: @@ -374,3 +374,14 @@ class EstablishmentPositionListView(generics.ListAPIView): permission_classes = (permissions.AllowAny, ) queryset = models.Position.objects.all() serializer_class = serializers.PositionBackSerializer + + +class EstablishmentAdminView(generics.ListAPIView): + """Establishment admin list view.""" + serializer_class = serializers.EstablishmentAdminListSerializer + permission_classes = (permissions.IsAuthenticatedOrReadOnly, ) + + def get_queryset(self): + establishment = get_object_or_404( + models.Establishment, slug=self.kwargs['slug']) + return User.objects.establishment_admin(establishment).distinct() From 8aa2cb71f36d366529b8bdc5c9be52613f6a9a89 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Fri, 13 Dec 2019 12:08:24 +0300 Subject: [PATCH 09/28] fix migrations --- apps/account/migrations/0023_auto_20191204_0916.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/account/migrations/0023_auto_20191204_0916.py b/apps/account/migrations/0023_auto_20191204_0916.py index 68d313a0..3b5fa7ea 100644 --- a/apps/account/migrations/0023_auto_20191204_0916.py +++ b/apps/account/migrations/0023_auto_20191204_0916.py @@ -17,6 +17,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='userrole', - unique_together={('user', 'role')}, + unique_together={('user', 'role', 'establishment', 'state')}, ), ] From 54db050f03e210b2db0901197d58e60ab6001ce3 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Fri, 13 Dec 2019 13:23:49 +0300 Subject: [PATCH 10/28] return tags_id__in --- apps/search_indexes/views.py | 21 +++------------------ apps/tag/serializers.py | 2 +- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index e567f212..cb5b448c 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -12,24 +12,9 @@ from search_indexes import serializers, filters, utils from search_indexes.documents import EstablishmentDocument, NewsDocument from search_indexes.documents.product import ProductDocument from utils.pagination import ESDocumentPagination -from tag.models import TagCategory -class CustomBaseDocumentViewSet(BaseDocumentViewSet): - def __init__(self, *args, **kwargs): - if self.filter_fields: - for name in TagCategory.objects.all().values('index_name'): - self.filter_fields.update({ - f'{name["index_name"]}_id': { - 'field': 'tags.id', - 'lookups': [constants.LOOKUP_QUERY_IN] - } - }) - - super().__init__(*args, **kwargs) - - -class NewsDocumentViewSet(CustomBaseDocumentViewSet): +class NewsDocumentViewSet(BaseDocumentViewSet): """News document ViewSet.""" document = NewsDocument @@ -108,7 +93,7 @@ class MobileNewsDocumentViewSet(NewsDocumentViewSet): ] -class EstablishmentDocumentViewSet(CustomBaseDocumentViewSet): +class EstablishmentDocumentViewSet(BaseDocumentViewSet): """Establishment document ViewSet.""" document = EstablishmentDocument @@ -333,7 +318,7 @@ class MobileEstablishmentDocumentViewSet(EstablishmentDocumentViewSet): ] -class ProductDocumentViewSet(CustomBaseDocumentViewSet): +class ProductDocumentViewSet(BaseDocumentViewSet): """Product document ViewSet.""" document = ProductDocument diff --git a/apps/tag/serializers.py b/apps/tag/serializers.py index c842774b..f6266060 100644 --- a/apps/tag/serializers.py +++ b/apps/tag/serializers.py @@ -123,7 +123,7 @@ class FiltersTagCategoryBaseSerializer(serializers.ModelSerializer): return obj in ['open_now', ] def get_param_name(self, obj): - return f'{obj.index_name}_id__in' + return 'tags_id__in' def get_fields(self, *args, **kwargs): fields = super(FiltersTagCategoryBaseSerializer, self).get_fields() From ae15a5e66bc05d3c6b2b66b8f5b62f95623ac580 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Fri, 13 Dec 2019 13:24:04 +0300 Subject: [PATCH 11/28] fix migration --- apps/account/migrations/0023_auto_20191204_0916.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/account/migrations/0023_auto_20191204_0916.py b/apps/account/migrations/0023_auto_20191204_0916.py index 3b5fa7ea..68d313a0 100644 --- a/apps/account/migrations/0023_auto_20191204_0916.py +++ b/apps/account/migrations/0023_auto_20191204_0916.py @@ -17,6 +17,6 @@ class Migration(migrations.Migration): ), migrations.AlterUniqueTogether( name='userrole', - unique_together={('user', 'role', 'establishment', 'state')}, + unique_together={('user', 'role')}, ), ] From 9fbb8f01def12a622323a7892f93ea239980d4b8 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Fri, 13 Dec 2019 14:57:15 +0300 Subject: [PATCH 12/28] dynamic filters --- apps/tag/serializers.py | 2 ++ apps/tag/views.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/apps/tag/serializers.py b/apps/tag/serializers.py index f6266060..b5e5a267 100644 --- a/apps/tag/serializers.py +++ b/apps/tag/serializers.py @@ -123,6 +123,8 @@ class FiltersTagCategoryBaseSerializer(serializers.ModelSerializer): return obj in ['open_now', ] def get_param_name(self, obj): + if obj.index_name == 'wine-color': + return 'wine_colors_id__in' return 'tags_id__in' def get_fields(self, *args, **kwargs): diff --git a/apps/tag/views.py b/apps/tag/views.py index 6a594220..3bb33975 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -213,6 +213,41 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): @staticmethod def remove_empty_filters(filters, facets): + # parse facets + if facets.get('_filter_tag'): + tags_to_preserve = list(map(lambda el: el['key'], facets['_filter_tag']['tag']['buckets'])) + if facets.get('_filter_wine_colors'): + wine_colors_to_preserve = list(map(lambda el: el['key'], facets['_filter_wine_colors']['wine_colors']['buckets'])) + if facets.get('_filter_wine_region_id'): + wine_regions_to_preserve = list(map(lambda el: el['key'], facets['_filter_wine_region_id']['wine_region_id']['buckets'])) + if facets.get('_filter_toque_number'): + toque_numbers = list(map(lambda el: el['key'], facets['_filter_toque_number']['toque_number']['buckets'])) + if facets.get('_filter_works_noon'): + works_noon = list(map(lambda el: el['key'], facets['_filter_works_noon']['works_noon']['buckets'])) + if facets.get('_filter_works_evening'): + works_evening = list(map(lambda el: el['key'], facets['_filter_works_evening']['works_evening']['buckets'])) + if facets.get('_filter_works_at_weekday'): + works_at_weekday = list(map(lambda el: el['key'], facets['_filter_works_at_weekday']['works_at_weekday']['buckets'])) + if facets.get('_filter_works_now'): + works_now = list(map(lambda el: el['key'], facets['_filter_works_now']['works_now']['buckets'])) + + # remove empty filters + for category in filters: + param_name = category.get('param_name') + if param_name == 'tags_id__in': + category['filters'] = list(filter(lambda tag: tag['id'] in tags_to_preserve, category['filters'])) + elif param_name == 'wine_colors_id__in': + category['filters'] = list(filter(lambda tag: tag['id'] in wine_colors_to_preserve, category['filters'])) + elif param_name == 'wine_region_id__in': + category['filters'] = list(filter(lambda tag: tag['id'] in wine_regions_to_preserve, category['filters'])) + elif param_name == 'toque_number__in': + category['filters'] = list(filter(lambda tag: tag['id'] in toque_numbers, category['filters'])) + elif param_name == 'works_noon__in': + category['filters'] = list(filter(lambda tag: tag['id'] in works_noon, category['filters'])) + elif param_name == 'works_evening__in': + category['filters'] = list(filter(lambda tag: tag['id'] in works_evening, category['filters'])) + elif param_name == 'works_at_weekday__in': + category['filters'] = list(filter(lambda tag: tag['id'] in works_at_weekday, category['filters'])) return filters From 833fada6d11910112502ee34b1edd12236b3a195 Mon Sep 17 00:00:00 2001 From: Anatoly Date: Fri, 13 Dec 2019 15:11:22 +0300 Subject: [PATCH 13/28] add fix migration issue --- db_migration_resolve.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 db_migration_resolve.txt diff --git a/db_migration_resolve.txt b/db_migration_resolve.txt new file mode 100644 index 00000000..770dac81 --- /dev/null +++ b/db_migration_resolve.txt @@ -0,0 +1,12 @@ +В случае возникновения проблемы с применением миграции account 0027: + +1 Удаляем unique together constrain для app - account + ALTER TABLE account_userrole + DROP CONSTRAINT account_userrole_user_id_role_id_26fa14c4_uniq; +2 Правим миграцию 0023 + migrations.AlterUniqueTogether( + name='userrole', + unique_together=set(), + ), +3 Применяем account 0027 +4 Возвращаем миграцию account 0023, в исходное состояние \ No newline at end of file From 8f6dd7e5c1c7bd8cd2cd14b21698119f0d298149 Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 16:17:35 +0300 Subject: [PATCH 14/28] Added related_object_ids --- apps/collection/models.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index 14bd99c0..d9256743 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -24,7 +24,8 @@ class CollectionNameMixin(models.Model): class CollectionDateMixin(models.Model): """CollectionDate mixin""" - start = models.DateTimeField(_('start')) + start = models.DateTimeField(blank=True, null=True, default=None, + verbose_name=_('start')) end = models.DateTimeField(blank=True, null=True, default=None, verbose_name=_('end')) @@ -110,20 +111,29 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, @property def related_object_names(self) -> list: """Return related object names.""" - raw_object_names = [] - for related_object in [related_object.name for related_object in self._related_objects]: - instances = getattr(self, f'{related_object}') + raw_object_names = {} + for related_object in [(related_object.id, related_object.name) for related_object in self._related_objects]: + instances = getattr(self, f'{related_object[1]}') if instances.exists(): for instance in instances.all(): - raw_object_names.append(instance.slug if hasattr(instance, 'slug') else None) + raw_object_names[related_object[0]] = instance.slug if hasattr(instance, 'slug') else None # parse slugs - object_names = [] + related_objects = [] + object_names = set() re_pattern = r'[\w]+' - for raw_name in raw_object_names: - result = re.findall(re_pattern, raw_name) - if result: object_names.append(' '.join(result).capitalize()) - return set(object_names) + for object_id in raw_object_names: + result = re.findall(re_pattern, raw_object_names[object_id]) + if result: + name = ' '.join(result).capitalize() + if name not in object_names: + related_objects.append({ + 'id': object_id, + 'name': name + }) + object_names.add(name) + + return related_objects class GuideTypeQuerySet(models.QuerySet): From f7e4effb9f2091686fda7771590cdad92b4fd67f Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Fri, 13 Dec 2019 16:48:52 +0300 Subject: [PATCH 15/28] dynamic filters --- apps/tag/views.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/tag/views.py b/apps/tag/views.py index 3bb33975..40118c2d 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -65,7 +65,7 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): serializer_class = serializers.FiltersTagCategoryBaseSerializer def list(self, request, *args, **kwargs): - queryset = self.filter_queryset(self.get_queryset()) + queryset = self.filter_queryset(self.get_queryset().exclude(public=False)) serializer = self.get_serializer(queryset, many=True) result_list = serializer.data @@ -99,6 +99,7 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): "index_name": "toque_number", "label_translated": "Toques", "param_name": "toque_number__in", + 'type': 'toque', "filters": [{ "id": toque_id, "index_name": "toque_%d" % toque_id, @@ -134,6 +135,7 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): "index_name": "works_noon", "label_translated": "Open noon", "param_name": "works_noon__in", + 'type': 'weekday', "filters": [{ "id": weekday, "index_name": week_days[weekday].lower(), @@ -148,6 +150,7 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): "index_name": "works_evening", "label_translated": "Open evening", "param_name": "works_evening__in", + 'type': 'weekday', "filters": [{ "id": weekday, "index_name": week_days[weekday].lower(), @@ -161,7 +164,7 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): "index_name": "open_now", "label_translated": "Open now", "param_name": "open_now", - "type": True + "type": 'bool', } result_list.append(works_now) @@ -170,6 +173,7 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): "index_name": "works_at_weekday", "label_translated": "Works at weekday", "param_name": "works_at_weekday__in", + 'type': 'weekday', "filters": [{ "id": weekday, "index_name": week_days[weekday].lower(), @@ -180,7 +184,16 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): search_view_class = self.define_search_view_by_request(request) facets = search_view_class.as_view({'get': 'list'})(self.mutate_request(self.request)).data['facets'] - return Response(self.remove_empty_filters(result_list, facets)) + result_list = self.remove_empty_filters(result_list, facets) + tag_category = list(filter(lambda x: x.get('index_name') == 'tag', result_list)) + result_list = [category for category in result_list if category.get('index_name') != 'tag'] + if len(tag_category): + tag_category = list(filter(lambda x: x.get('index_name') == 'pop', tag_category[0]['filters'])) + if len(tag_category): # we have Pop tag in our results + tag_category = tag_category[0] + tag_category['param_name'] = 'tags_id__in' + result_list.append(tag_category) + return Response(result_list) @staticmethod def mutate_request(request): From 525658f39bae148af0e4845eacbd2d822338ba68 Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 18:32:06 +0300 Subject: [PATCH 16/28] Reformat ordering --- apps/collection/filters.py | 8 ++++++++ apps/collection/urls/back.py | 6 +----- apps/collection/views/back.py | 18 ++---------------- 3 files changed, 11 insertions(+), 21 deletions(-) create mode 100644 apps/collection/filters.py diff --git a/apps/collection/filters.py b/apps/collection/filters.py new file mode 100644 index 00000000..a97b47d1 --- /dev/null +++ b/apps/collection/filters.py @@ -0,0 +1,8 @@ +from rest_framework import filters + + +class CollectionBackOfficeOrderingFilter(filters.BaseFilterBackend): + """ Filter ordering """ + + def filter_queryset(self, request, queryset, view): + return queryset.order_by('rank', '-start') diff --git a/apps/collection/urls/back.py b/apps/collection/urls/back.py index f97a3945..972f5285 100644 --- a/apps/collection/urls/back.py +++ b/apps/collection/urls/back.py @@ -8,9 +8,5 @@ app_name = 'collection' router = SimpleRouter() router.register(r'', views.CollectionBackOfficeViewSet) -urlpatterns = [ - path('/', views.CollectionBackOfficeView.as_view(), name='detail'), -] - -urlpatterns += router.urls +urlpatterns = router.urls diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index fdb441c2..f9b119aa 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,9 +1,8 @@ -from rest_framework import generics from rest_framework import mixins from rest_framework import permissions from rest_framework import viewsets -from rest_framework.response import Response +from collection import filters from collection import models from collection.serializers import back as serializers from utils.views import BindObjectMixin @@ -28,6 +27,7 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, permission_classes = (permissions.IsAuthenticated,) queryset = models.Collection.objects.all() + filter_backends = [filters.CollectionBackOfficeOrderingFilter] serializer_class = serializers.CollectionBackOfficeSerializer bind_object_serializer_class = serializers.CollectionBindObjectSerializer @@ -50,17 +50,3 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, collection.establishments.remove(related_object) elif obj_type == self.bind_object_serializer_class.PRODUCT: collection.products.remove(related_object) - - def list(self, request, *args, **kwargs): - queryset = self.filter_queryset(self.get_queryset()).order_by('rank', '-start') - serializer = self.get_serializer(queryset, many=True) - return Response(serializer.data) - - -class CollectionBackOfficeView(generics.GenericAPIView): - """ViewS for Collection model.""" - - pagination_class = None - permission_classes = (permissions.IsAuthenticated,) - queryset = models.Collection.objects.all() - serializer_class = serializers.CollectionBackOfficeSerializer From c5056224e07b487ef1f8c07192644136ed6bfd98 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Fri, 13 Dec 2019 21:19:15 +0300 Subject: [PATCH 17/28] sort filters --- apps/tag/views.py | 61 +++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/apps/tag/views.py b/apps/tag/views.py index 40118c2d..2b8eb4ef 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -63,6 +63,17 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): """ViewSet for TagCategory model.""" serializer_class = serializers.FiltersTagCategoryBaseSerializer + index_name_to_order = { + 'open_now': 9, + 'works_noon': 8, + 'works_evening': 7, + 'pop': 6, + 'category': 5, + 'toque_number': 4, + 'cuisine': 3, + 'moment': 2, + 'service': 1, + } def list(self, request, *args, **kwargs): queryset = self.filter_queryset(self.get_queryset().exclude(public=False)) @@ -77,7 +88,7 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): elif query_params.get('product_type'): params_type = query_params.get('product_type') - week_days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") + week_days = tuple(map(_, ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))) flags = ('toque_number', 'wine_region', 'works_noon', 'works_evening', 'works_now', 'works_at_weekday') filter_flags = {flag_name: False for flag_name in flags} additional_flags = [] @@ -94,20 +105,6 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): for flag_name in additional_flags: filter_flags[flag_name] = True - if filter_flags['toque_number']: - toques = { - "index_name": "toque_number", - "label_translated": "Toques", - "param_name": "toque_number__in", - 'type': 'toque', - "filters": [{ - "id": toque_id, - "index_name": "toque_%d" % toque_id, - "label_translated": "Toque %d" % toque_id - } for toque_id in range(6)] - } - result_list.append(toques) - if request.query_params.get('product_type') == ProductType.WINE: wine_region_id = query_params.get('wine_region_id__in') @@ -130,6 +127,24 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): result_list.append(wine_regions) + for item in result_list: + if 'filters' in item: + item['filters'].sort(key=lambda x: x.get('label_translated')) + + if filter_flags['toque_number']: + toques = { + "index_name": "toque_number", + "label_translated": "Toques", + "param_name": "toque_number__in", + 'type': 'toque', + "filters": [{ + "id": toque_id, + "index_name": "toque_%d" % toque_id, + "label_translated": "Toque %d" % toque_id + } for toque_id in range(6)] + } + result_list.append(toques) + if filter_flags['works_noon']: works_noon = { "index_name": "works_noon", @@ -193,6 +208,7 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): tag_category = tag_category[0] tag_category['param_name'] = 'tags_id__in' result_list.append(tag_category) + result_list.sort(key=lambda x: self.index_name_to_order.get(x.get('index_name'), 0), reverse=True) return Response(result_list) @staticmethod @@ -230,9 +246,11 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): if facets.get('_filter_tag'): tags_to_preserve = list(map(lambda el: el['key'], facets['_filter_tag']['tag']['buckets'])) if facets.get('_filter_wine_colors'): - wine_colors_to_preserve = list(map(lambda el: el['key'], facets['_filter_wine_colors']['wine_colors']['buckets'])) + wine_colors_to_preserve = list( + map(lambda el: el['key'], facets['_filter_wine_colors']['wine_colors']['buckets'])) if facets.get('_filter_wine_region_id'): - wine_regions_to_preserve = list(map(lambda el: el['key'], facets['_filter_wine_region_id']['wine_region_id']['buckets'])) + wine_regions_to_preserve = list( + map(lambda el: el['key'], facets['_filter_wine_region_id']['wine_region_id']['buckets'])) if facets.get('_filter_toque_number'): toque_numbers = list(map(lambda el: el['key'], facets['_filter_toque_number']['toque_number']['buckets'])) if facets.get('_filter_works_noon'): @@ -240,7 +258,8 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): if facets.get('_filter_works_evening'): works_evening = list(map(lambda el: el['key'], facets['_filter_works_evening']['works_evening']['buckets'])) if facets.get('_filter_works_at_weekday'): - works_at_weekday = list(map(lambda el: el['key'], facets['_filter_works_at_weekday']['works_at_weekday']['buckets'])) + works_at_weekday = list( + map(lambda el: el['key'], facets['_filter_works_at_weekday']['works_at_weekday']['buckets'])) if facets.get('_filter_works_now'): works_now = list(map(lambda el: el['key'], facets['_filter_works_now']['works_now']['buckets'])) @@ -250,9 +269,11 @@ class FiltersTagCategoryViewSet(TagCategoryViewSet): if param_name == 'tags_id__in': category['filters'] = list(filter(lambda tag: tag['id'] in tags_to_preserve, category['filters'])) elif param_name == 'wine_colors_id__in': - category['filters'] = list(filter(lambda tag: tag['id'] in wine_colors_to_preserve, category['filters'])) + category['filters'] = list( + filter(lambda tag: tag['id'] in wine_colors_to_preserve, category['filters'])) elif param_name == 'wine_region_id__in': - category['filters'] = list(filter(lambda tag: tag['id'] in wine_regions_to_preserve, category['filters'])) + category['filters'] = list( + filter(lambda tag: tag['id'] in wine_regions_to_preserve, category['filters'])) elif param_name == 'toque_number__in': category['filters'] = list(filter(lambda tag: tag['id'] in toque_numbers, category['filters'])) elif param_name == 'works_noon__in': From 4eff4883697a3e06dd3fc2100007b6365d703b15 Mon Sep 17 00:00:00 2001 From: dormantman Date: Fri, 13 Dec 2019 21:39:09 +0300 Subject: [PATCH 18/28] Added description field --- apps/collection/serializers/back.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index f41e3875..c11f9fbf 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -34,7 +34,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): 'country', 'country_id', # 'block_size', - # 'description', + 'description', 'slug', # 'start', # 'end', From a120ea1f1bf181f4a478cdb5d1ada90caf95df1a Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Fri, 13 Dec 2019 22:05:16 +0300 Subject: [PATCH 19/28] fix search for products --- apps/search_indexes/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index cb5b448c..4b18bea6 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -390,7 +390,7 @@ class ProductDocumentViewSet(BaseDocumentViewSet): 'lookups': [constants.LOOKUP_QUERY_IN], }, 'country': { - 'field': 'establishment.address.city.country.code', + 'field': 'establishment.city.country.code', }, 'wine_colors_id': { 'field': 'wine_colors.id', From b847de11831fdc03dc6b3355b05d2881d76d8c08 Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 01:01:56 +0300 Subject: [PATCH 20/28] Added collection migration --- .../migrations/0024_auto_20191215_2156.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 apps/collection/migrations/0024_auto_20191215_2156.py diff --git a/apps/collection/migrations/0024_auto_20191215_2156.py b/apps/collection/migrations/0024_auto_20191215_2156.py new file mode 100644 index 00000000..6e11668e --- /dev/null +++ b/apps/collection/migrations/0024_auto_20191215_2156.py @@ -0,0 +1,23 @@ +# Generated by Django 2.2.7 on 2019-12-15 21:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('collection', '0023_advertorial'), + ] + + operations = [ + migrations.AddField( + model_name='collection', + name='rank', + field=models.IntegerField(default=None, null=True), + ), + migrations.AlterField( + model_name='collection', + name='start', + field=models.DateTimeField(blank=True, default=None, null=True, verbose_name='start'), + ), + ] From def1372317f409d457fd0a69c0b3fa740a54159f Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 01:02:21 +0300 Subject: [PATCH 21/28] Change ordering format --- apps/collection/filters.py | 8 -------- apps/collection/views/back.py | 8 ++++++-- 2 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 apps/collection/filters.py diff --git a/apps/collection/filters.py b/apps/collection/filters.py deleted file mode 100644 index a97b47d1..00000000 --- a/apps/collection/filters.py +++ /dev/null @@ -1,8 +0,0 @@ -from rest_framework import filters - - -class CollectionBackOfficeOrderingFilter(filters.BaseFilterBackend): - """ Filter ordering """ - - def filter_queryset(self, request, queryset, view): - return queryset.order_by('rank', '-start') diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index f9b119aa..787570cc 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,8 +1,9 @@ +from django_filters.rest_framework import DjangoFilterBackend from rest_framework import mixins from rest_framework import permissions from rest_framework import viewsets +from rest_framework.filters import OrderingFilter -from collection import filters from collection import models from collection.serializers import back as serializers from utils.views import BindObjectMixin @@ -27,10 +28,13 @@ class CollectionBackOfficeViewSet(mixins.CreateModelMixin, permission_classes = (permissions.IsAuthenticated,) queryset = models.Collection.objects.all() - filter_backends = [filters.CollectionBackOfficeOrderingFilter] + filter_backends = [DjangoFilterBackend, OrderingFilter] serializer_class = serializers.CollectionBackOfficeSerializer bind_object_serializer_class = serializers.CollectionBindObjectSerializer + ordering_fields = ('rank', 'start') + ordering = ('-start', ) + def perform_binding(self, serializer): data = serializer.validated_data collection = data.pop('collection') From a9f5a5b98f9338ac298e30e9b3ecf1784cff510f Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 13:34:54 +0300 Subject: [PATCH 22/28] Deleted description field --- apps/collection/migrations/0024_auto_20191215_2156.py | 4 ++++ apps/collection/models.py | 6 +++--- apps/collection/serializers/back.py | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/collection/migrations/0024_auto_20191215_2156.py b/apps/collection/migrations/0024_auto_20191215_2156.py index 6e11668e..1b494867 100644 --- a/apps/collection/migrations/0024_auto_20191215_2156.py +++ b/apps/collection/migrations/0024_auto_20191215_2156.py @@ -20,4 +20,8 @@ class Migration(migrations.Migration): name='start', field=models.DateTimeField(blank=True, default=None, null=True, verbose_name='start'), ), + migrations.RemoveField( + model_name='collection', + name='description', + ) ] diff --git a/apps/collection/models.py b/apps/collection/models.py index d9256743..be445394 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -74,9 +74,9 @@ class Collection(ProjectBaseMixin, CollectionDateMixin, block_size = JSONField( _('collection block properties'), null=True, blank=True, default=None, help_text='{"width": "250px", "height":"250px"}') - description = TJSONField( - _('description'), null=True, blank=True, - default=None, help_text='{"en-GB":"some text"}') + # description = TJSONField( + # _('description'), null=True, blank=True, + # default=None, help_text='{"en-GB":"some text"}') slug = models.SlugField(max_length=50, unique=True, verbose_name=_('Collection slug'), editable=True, null=True) old_id = models.IntegerField(null=True, blank=True) diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index c11f9fbf..f41e3875 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -34,7 +34,7 @@ class CollectionBackOfficeSerializer(CollectionBaseSerializer): 'country', 'country_id', # 'block_size', - 'description', + # 'description', 'slug', # 'start', # 'end', From c2a520b518655b6f6a3ce4443e717dd5979464fa Mon Sep 17 00:00:00 2001 From: dormantman Date: Mon, 16 Dec 2019 13:59:04 +0300 Subject: [PATCH 23/28] Reformat code style --- apps/collection/models.py | 7 ++++--- apps/collection/serializers/back.py | 3 ++- apps/collection/views/back.py | 4 +--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/collection/models.py b/apps/collection/models.py index be445394..099491ac 100644 --- a/apps/collection/models.py +++ b/apps/collection/models.py @@ -6,9 +6,10 @@ from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.utils.translation import gettext_lazy as _ -from utils.models import ProjectBaseMixin, URLImageMixin -from utils.models import TJSONField -from utils.models import TranslatedFieldsMixin +from utils.models import ( + ProjectBaseMixin, TJSONField, TranslatedFieldsMixin, + URLImageMixin, +) from utils.querysets import RelatedObjectsCountMixin diff --git a/apps/collection/serializers/back.py b/apps/collection/serializers/back.py index f41e3875..bdc97e91 100644 --- a/apps/collection/serializers/back.py +++ b/apps/collection/serializers/back.py @@ -7,7 +7,8 @@ from location.models import Country from location.serializers import CountrySimpleSerializer from product.models import Product from utils.exceptions import ( - BindingObjectNotFound, RemovedBindingObjectNotFound, ObjectAlreadyAdded + BindingObjectNotFound, ObjectAlreadyAdded, + RemovedBindingObjectNotFound, ) diff --git a/apps/collection/views/back.py b/apps/collection/views/back.py index 787570cc..0b13034b 100644 --- a/apps/collection/views/back.py +++ b/apps/collection/views/back.py @@ -1,7 +1,5 @@ from django_filters.rest_framework import DjangoFilterBackend -from rest_framework import mixins -from rest_framework import permissions -from rest_framework import viewsets +from rest_framework import mixins, permissions, viewsets from rest_framework.filters import OrderingFilter from collection import models From 586f6e373bc7563301e6ad177e21cfcc621f4617 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 15:30:05 +0300 Subject: [PATCH 24/28] Anatoly, dont erase working code during refactoring pls --- apps/establishment/models.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index ab7f14fa..5ff6f921 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -541,9 +541,15 @@ class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin, def visible_tags(self): return super().visible_tags \ .exclude(category__index_name__in=['guide', 'collection', 'purchased_item', - 'business_tag', 'business_tags_de', 'tag']) + 'business_tag', 'business_tags_de']) \ + .exclude(value__in=['rss', 'rss_selection']) # todo: recalculate toque_number + @property + def visible_tags_detail(self): + """Removes some tags from detail Establishment representation""" + return self.visible_tags.exclude(category__index_name__in=['tag']) + def recalculate_toque_number(self): toque_number = 0 if self.address and self.public_mark: From cf001b3aabbb215a833aef67ea5a691a1562fd35 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 17:02:45 +0300 Subject: [PATCH 25/28] return news object after binding --- apps/news/views.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/news/views.py b/apps/news/views.py index c8acb3ac..732228b4 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -1,7 +1,7 @@ """News app views.""" from django.conf import settings from django.shortcuts import get_object_or_404 -from rest_framework import generics, permissions +from rest_framework import generics, permissions, response from news import filters, models, serializers from rating.tasks import add_rating @@ -106,6 +106,14 @@ class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView, CreateDestroyGalleryViewMixin): """Resource for a create gallery for news for back-office users.""" serializer_class = serializers.NewsBackOfficeGallerySerializer + permission_classes = (permissions.AllowAny, ) + + def create(self, request, *args, **kwargs): + _ = super().create(request, *args, **kwargs) + news_qs = self.filter_queryset(self.get_queryset()) + return response.Response( + data=serializers.NewsDetailSerializer(get_object_or_404(news_qs, pk=kwargs.get('pk'))).data + ) def get_object(self): """ From f4fff47d68565a935da4f3165037874e49ef3379 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 17:04:52 +0300 Subject: [PATCH 26/28] return news object after binding #2 --- apps/news/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/news/views.py b/apps/news/views.py index 732228b4..f59ad2d6 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -106,7 +106,6 @@ class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView, CreateDestroyGalleryViewMixin): """Resource for a create gallery for news for back-office users.""" serializer_class = serializers.NewsBackOfficeGallerySerializer - permission_classes = (permissions.AllowAny, ) def create(self, request, *args, **kwargs): _ = super().create(request, *args, **kwargs) From b25f387c9be6af1dbfbdb3e09cf1dc5db3d682fa Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 17:29:01 +0300 Subject: [PATCH 27/28] news search --- apps/search_indexes/views.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index 4b18bea6..f088bf8b 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -61,11 +61,18 @@ class NewsDocumentViewSet(BaseDocumentViewSet): ) filter_fields = { + 'tags_id': { + 'field': 'tags.id', + 'lookups': [ + constants.LOOKUP_QUERY_IN, + constants.LOOKUP_QUERY_EXCLUDE, + ], + }, 'tag': { 'field': 'tags.id', 'lookups': [ constants.LOOKUP_QUERY_IN, - constants.LOOKUP_QUERY_EXCLUDE + constants.LOOKUP_QUERY_EXCLUDE, ] }, 'tag_value': { From e68142bf2eb63549c08288b900fd01cc1bb3a5f2 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Mon, 16 Dec 2019 18:43:15 +0300 Subject: [PATCH 28/28] BO news list by country --- apps/news/views.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/news/views.py b/apps/news/views.py index f59ad2d6..fe9a75e7 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -99,7 +99,10 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView, def get_queryset(self): """Override get_queryset method.""" - return super().get_queryset().with_extended_related() + qs = super().get_queryset().with_extended_related() + if self.request.country_code: + qs = qs.by_country_code(self.request.country_code) + return qs class NewsBackOfficeGalleryCreateDestroyView(NewsBackOfficeMixinView,