"""Establishment app views.""" from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.db import transaction from django.db.models.query_utils import Q from django.http import Http404 from django.shortcuts import get_object_or_404 from django_filters.rest_framework import DjangoFilterBackend from rest_framework import generics, response, status from rest_framework.response import Response from account.models import User, Role, UserRole from collection.models import Guide from establishment import filters, models, serializers from establishment.models import EstablishmentEmployee, Menu from main import models as main_models from main import serializers as main_serializers from timetable.models import Timetable from timetable.serialziers import ScheduleCreateSerializer, ScheduleRUDSerializer from utils.methods import get_permission_classes from utils.permissions import (IsEstablishmentAdministrator, IsEstablishmentManager) from utils.views import CreateDestroyGalleryViewMixin class MenuRUDMixinViews: """Menu mixin""" def get_object(self): instance = self.get_queryset().filter( Q(establishment__slug=self.kwargs.get('slug')) | Q(establishment__id=self.kwargs.get('pk')) ).first() if instance is None: raise Http404 return instance class EstablishmentMixinViews: """Establishment mixin.""" def get_queryset(self): """Overridden method 'get_queryset'.""" queryset = models.Establishment.objects.with_base_related if hasattr(self, 'request') and \ (hasattr(self.request, 'user') and hasattr(self.request, 'country_code')): return queryset().available_establishments(self.request.user, self.request.country_code) return queryset().none() class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAPIView): """Establishment list/create view.""" filter_class = filters.EstablishmentFilter serializer_class = serializers.EstablishmentListCreateSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def get_queryset(self): return super().get_queryset() \ .with_extended_address_related() \ .with_certain_tag_category_related('category', 'restaurant_category') \ .with_certain_tag_category_related('cuisine', 'restaurant_cuisine') \ .with_certain_tag_category_related('shop_category', 'artisan_category') \ .with_certain_tag_category_related('distillery_type', 'distillery_type') \ .with_certain_tag_category_related('producer_type', 'food_producer') \ .with_reviews_sorted() class EmployeeEstablishmentPositionsView(generics.ListAPIView): """ ## Establishment employee positions filtered by employee identifier. ### *GET* #### Description Return paginated list of results from an intermediate table filtered by employee identifier, that contains connection between employee establishment, employee hiring dates, position, status `'I' (Idle)`, `'A' (Accepted)`, `'D' (Declined)`. ##### Response ``` { "count": 58, "next": 2, "previous": null, "results": [ { "id": 1, ... } ] } ``` """ queryset = models.EstablishmentEmployee.objects.all() serializer_class = serializers.EstablishmentEmployeePositionsSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) def get_queryset(self): employee_pk = self.kwargs.get('pk') return super().get_queryset().filter(employee__id=employee_pk).all().prefetch_related( 'establishment').select_related('position') class EmployeeEstablishmentsListView(generics.ListAPIView): """ ## Employee establishments filtered by employee identifier. ### *GET* #### Description Return paginated list of establishments filtered by employee identifier. ##### Response ``` { "count": 58, "next": 2, "previous": null, "results": [ { "id": 1, ... } ] } ``` """ serializer_class = serializers.EstablishmentListCreateSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def get_queryset(self): pk = self.kwargs.get('pk') employee = get_object_or_404(models.Employee, pk=pk) return employee.establishments.with_extended_related() class EmployeePositionsListView(generics.ListAPIView): """ ## Paginated list of establishments filtered by employee identifier ### *GET* #### Description Return a paginated list of establishments of an employee by employee identifier. ##### Response ``` { "count": 2, "next": null, "previous": null, "results": [ { "id": 1, ... } } ``` """ queryset = models.Establishment.objects.all() serializer_class = serializers.EstablishmentPositionListSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) def get_queryset(self): pk = self.kwargs.get('pk') employee = get_object_or_404(models.Employee, pk=pk) return employee.establishments.with_extended_related() class EstablishmentRUDView(EstablishmentMixinViews, generics.RetrieveUpdateDestroyAPIView): """ Establishment by slug Implements get, update, delete methods **GET** ``` EstablishmentRUDView GET method Implement getting Establishment by slug ``` **PUT** ``` EstablishmentRUDView PUT method Implement update of Establishment by slug ``` **PATCH** ``` EstablishmentRUDView PATCH method Implement partial update of Establishment by slug ``` **DELETE** ``` EstablishmentRUDView DELETE method Implement delete Establishment by slug ``` """ lookup_field = 'slug' serializer_class = serializers.EstablishmentRUDSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def get_queryset(self): """An overridden get_queryset method.""" qs = super(EstablishmentRUDView, self).get_queryset() return qs.prefetch_related( 'establishmentemployee_set', 'establishmentemployee_set__establishment', ) class EstablishmentScheduleRUDView(EstablishmentMixinViews, generics.RetrieveUpdateDestroyAPIView): """ Establishment schedule RUD view **GET** ``` Implement getting object of Establishment schedule. ``` **PUT** ``` Implement update Establishment schedule. ``` **PATCH** ``` Implement partial update Establishment schedule. ``` **DELETE** ``` Implement delete Establement schedule. ``` """ lookup_field = 'slug' serializer_class = ScheduleRUDSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def get_object(self): """ Returns the object the view is displaying. """ establishment_slug = self.kwargs['slug'] schedule_id = self.kwargs['schedule_id'] establishment = get_object_or_404(klass=super(EstablishmentScheduleRUDView, self).get_queryset(), slug=establishment_slug) schedule = get_object_or_404(klass=establishment.schedule, id=schedule_id) # May raise a permission denied self.check_object_permissions(self.request, establishment) self.check_object_permissions(self.request, schedule) return schedule class EstablishmentScheduleCreateView(generics.CreateAPIView): """ ## Create establishment schedule ### *POST* #### Description Create schedule for establishment by establishment `slug`. ##### Request Required: * weekday (`enum`) ``` 0 (Monday), 1 (Tuesday), 2 (Wednesday), 3 (Thursday), 4 (Friday), 5 (Saturday), 6 (Sunday) ``` Non-required: * lunch_start (str) - time in a format (`ISO-8601`, e.g. - `hh:mm:ss`) * lunch_end (str) - time in a format (`ISO-8601`, e.g. - `hh:mm:ss`) * dinner_start (str) - time in a format (`ISO-8601`, e.g. - `hh:mm:ss`) * dinner_end (str) - time in a format (`ISO-8601`, e.g. - `hh:mm:ss`) * opening_at (str) - time in a format (`ISO-8601`, e.g. - `hh:mm:ss`) * closed_at (str) - time in a format (`ISO-8601`, e.g. - `hh:mm:ss`) ##### Response ``` { "id": 1, ... } ``` """ lookup_field = 'slug' serializer_class = ScheduleCreateSerializer queryset = Timetable.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class CardAndWinesListView(generics.RetrieveAPIView): permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) serializer_class = serializers.CardAndWinesSerializer queryset = models.Establishment.objects.with_base_related() def get_object(self): establishment = models.Establishment.objects.prefetch_plates() \ .filter(pk=self.kwargs['establishment_id']) \ .first() if establishment is None: raise Http404 plates = [] for menu in establishment.menu_set.prefetch_related('plates').exclude(type=Menu.FORMULAS): plates += list(menu.plates.all().prefetch_related('menu')) setattr(establishment, 'card_and_wine_plates', plates) return establishment class CreateMenuForCertainEstablishmentView(generics.CreateAPIView): """Creates formulas menu for certain establishment""" permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) # from rest_framework.permissions import AllowAny # permission_classes = (AllowAny, ) queryset = models.Menu.objects.with_base_related().by_type(menu_type=models.Menu.FORMULAS) serializer_class = serializers.MenuBackOfficeSerializer def create(self, request, *args, **kwargs): data = request.data.copy() data['establishment_id'] = kwargs['establishment_id'] data['type'] = models.Menu.FORMULAS serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) with transaction.atomic(): self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) class MenuListCreateView(generics.ListCreateAPIView): """Menu list create view. This view works only with menu formulas type""" serializer_class = serializers.MenuBackOfficeSerializer queryset = models.Menu.objects.with_base_related().by_type(menu_type=models.Menu.FORMULAS) permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) filter_backends = (DjangoFilterBackend,) filterset_fields = ( 'establishment', 'establishment__slug', ) def create(self, request, *args, **kwargs): response_data = [] with transaction.atomic(): establishment = get_object_or_404(models.Establishment, pk=next(iter(request.data))['establishment_id']) update_ids = [menu['id'] for menu in request.data if 'id' in menu] for menu_instance in establishment.menu_set.by_type(models.Menu.FORMULAS): if menu_instance.pk not in update_ids: menu_instance.delete() for menu in request.data: menu.update({'type': models.Menu.FORMULAS}) if 'id' in menu: instance = get_object_or_404(Menu, pk=menu['id']) serializer = self.get_serializer(instance, data=menu) else: serializer = self.get_serializer(data=menu) serializer.is_valid(raise_exception=True) serializer.save() response_data.append(serializer.data) return Response(response_data, status=status.HTTP_201_CREATED) class MenuRUDView(generics.UpdateAPIView, generics.DestroyAPIView): """Menu RUD view.""" serializer_class = serializers.MenuBackOfficeSerializer queryset = models.Menu.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def get_object(self): return get_object_or_404(klass=models.Menu, pk=self.kwargs['menu_id']) def update(self, request, *args, **kwargs): partial = kwargs.pop('partial', False) instance = self.get_object() data = request.data.copy() data['establishment_id'] = instance.establishment.pk serializer = self.get_serializer(instance, data=data, partial=partial) serializer.is_valid(raise_exception=True) with transaction.atomic(): self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None): # If 'prefetch_related' has been applied to a queryset, we need to # forcibly invalidate the prefetch cache on the instance. instance._prefetched_objects_cache = {} return Response(serializer.data) class MenuUploadsRUDView(generics.RetrieveDestroyAPIView): """Menu uploads RUD view.""" serializer_class = serializers.MenuFilesSerializers queryset = models.MenuFiles.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class EstablishmentWineView(generics.CreateAPIView): """Create and update establishment wine""" serializer_class = serializers.EstablishmentBackOfficeWineSerializer queryset = models.EstablishmentBackOfficeWine.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def create(self, request, *args, **kwargs): data = request.data.copy() data.update({'establishment_id': self.kwargs['establishment_id']}) if 'id' in data: """Update""" instance = get_object_or_404(models.EstablishmentBackOfficeWine, pk=data['id']) serializer = self.get_serializer(instance, data=data) else: """create""" serializer = self.get_serializer(data=data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) class DishCreateView(generics.CreateAPIView): """View for creating and binding dish to establishment""" serializer_class = serializers.CardAndWinesPlatesSerializer queryset = models.Plate.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class DishUpdateDeleteView(generics.UpdateAPIView, generics.DestroyAPIView): serializer_class = serializers.CardAndWinesPlatesSerializer queryset = models.Plate.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def get_object(self): return get_object_or_404(models.Plate, pk=self.kwargs['dish_id']) def update(self, request, *args, **kwargs): with transaction.atomic(): return super().update(request, *args, **kwargs) class MenuUploadsCreateView(generics.CreateAPIView): """Menu uploads list view""" serializer_class = serializers.MenuFilesSerializers queryset = models.MenuFiles.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class SocialChoiceListCreateView(generics.ListCreateAPIView): """SocialChoice list create view.""" serializer_class = serializers.SocialChoiceSerializers queryset = models.SocialChoice.objects.all() pagination_class = None permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class SocialChoiceRUDView(generics.RetrieveUpdateDestroyAPIView): """SocialChoice RUD view.""" serializer_class = serializers.SocialChoiceSerializers queryset = models.SocialChoice.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class SocialListCreateView(generics.ListCreateAPIView): """Social list create view.""" serializer_class = serializers.SocialNetworkSerializers queryset = models.SocialNetwork.objects.all() pagination_class = None permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class SocialRUDView(generics.RetrieveUpdateDestroyAPIView): """Social RUD view.""" serializer_class = serializers.SocialNetworkSerializers queryset = models.SocialNetwork.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class PlateListCreateView(generics.ListCreateAPIView): """Plate list create view.""" serializer_class = serializers.PlatesSerializers queryset = models.Plate.objects.all() pagination_class = None permission_classes = get_permission_classes( IsEstablishmentAdministrator, IsEstablishmentManager, ) class PlateRUDView(generics.RetrieveUpdateDestroyAPIView): """Plate RUD view.""" serializer_class = serializers.PlatesSerializers queryset = models.Plate.objects.all() permission_classes = get_permission_classes( IsEstablishmentAdministrator, IsEstablishmentManager, ) class PhonesListCreateView(generics.ListCreateAPIView): """Phones list create view.""" serializer_class = serializers.ContactPhoneBackSerializers queryset = models.ContactPhone.objects.all() pagination_class = None permission_classes = get_permission_classes( IsEstablishmentAdministrator, IsEstablishmentManager, ) class PhonesRUDView(generics.RetrieveUpdateDestroyAPIView): """Phones RUD view.""" serializer_class = serializers.ContactPhoneBackSerializers queryset = models.ContactPhone.objects.all() permission_classes = get_permission_classes( IsEstablishmentAdministrator, IsEstablishmentManager, ) class EmailListCreateView(generics.ListCreateAPIView): """ Email list create view. **GET** ``` Implement getting Email list. ``` **POST** ``` Implement creating Email ``` """ serializer_class = serializers.ContactEmailBackSerializers queryset = models.ContactEmail.objects.all() pagination_class = None permission_classes = get_permission_classes( IsEstablishmentAdministrator, IsEstablishmentManager, ) class EmailRUDView(generics.RetrieveUpdateDestroyAPIView): """ Email RUD view. **GET** ``` Implement getting Email object. ``` **PUT** ``` Implement updating Email. ``` **PATCH** ``` Implement partial updating Email. ``` **DELETE** ``` Implement deleting Email. ``` """ serializer_class = serializers.ContactEmailBackSerializers queryset = models.ContactEmail.objects.all() permission_classes = get_permission_classes( IsEstablishmentAdministrator, IsEstablishmentManager, ) class EmployeeListCreateView(generics.ListCreateAPIView): """ ## Employee list/create view. ### *GET* #### Description Return paginated list of employees with available filters: * search (`str`) - filter by name or last name with mistakes * position_id (`int`) - filter by employees position identifier * public_mark (`str`) - filter by establishment public mark * toque_number (`str`) - filter by establishment toque number * username (`str`) - filter by a username or name #### Response ``` { "count": 12765, "next": 2, "previous": null, "results": [ { "id": 1, ... } { ``` ### *POST* #### Description Create a new employee. #### Response ``` { "id": 1, ... { ``` #### Request Required fields: * name (`str`) - employee name Non-required fields: * name (`str`) - employee name * last_name (`str`) - employee last name * user (`int`) - user identifier * sex (`int`) - enum: `0 (Male), 1 (Female)` * birth_date (`str`) - birth datetime (datetime in a format `ISO-8601`) * email (`str`) - email address * phone (`str`) - phone number in a format `E164` * photo_id (`int`) - photo identifier * available_for_events (bool) - flag that responds for availability for events """ filter_class = filters.EmployeeBackFilter serializer_class = serializers.EmployeeBackSerializers queryset = models.Employee.objects.all().distinct().with_back_office_related() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def get_queryset(self): qs = super().get_queryset() if self.request.country_code: qs = qs.filter(establishments__address__city__country__code=self.request.country_code) return qs class EmployeesListSearchViews(generics.ListAPIView): """ ## Employee search view. ### *GET* ##### Description Return a non-paginated list of employees. Available filters: * search (`str`) - filter by name or last name with mistakes * position_id (`int`) - filter by employees position identifier * public_mark (`str`) - filter by establishment public mark * toque_number (`str`) - filter by establishment toque number * username (`str`) - filter by a username or name (with limitations by the minimum number of characters) ###### Response ``` [ { "id": 1, ... } ] ``` """ pagination_class = None filter_class = filters.EmployeeBackSearchFilter serializer_class = serializers.EmployeeBackSerializers queryset = ( models.Employee.objects.with_back_office_related() .select_related('photo') ) permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class EstablishmentEmployeeListView(generics.ListCreateAPIView): """ ## Establishment employees List/Create view. ### *GET* #### Description Returning non-paginated list of employees by establishment identifier. ##### Response E.g.: ``` [ { "id": 1, ... } ] ``` ### *POST* #### Description Create a new instance of employee for establishment by establishment identifier. #### Request Required: * name (`str`) - employee name Additional: * last_name (`str`) - employee last name * user (`int`) - user identifier * sex (`int`) - enum: `0 (Male), 1 (Female)` * birth_date (`str`) - birth datetime (datetime in a format `ISO-8601`) * email (`str`) - email address * phone (`str`) - phone number in a format `E164` * available_for_events (bool) - flag that responds for availability for events * photo_id (`int`) - photo identifier #### Response ``` { "id": 1, ... } ``` """ serializer_class = serializers.EstEmployeeBackSerializer pagination_class = None permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) def get_queryset(self): establishment_id = self.kwargs['establishment_id'] establishment = get_object_or_404(models.Establishment, pk=establishment_id) self.kwargs['establishment_instance'] = establishment self.kwargs['establishment_instance_subtypes'] = list(establishment.establishment_subtypes.all()) self.kwargs['establishment_instance_type'] = establishment.establishment_type return models.Employee.objects.filter( establishmentemployee__establishment_id=establishment_id, ).distinct() class EmployeeRUDView(generics.RetrieveUpdateDestroyAPIView): """ ## Employee Retrieve/Update/Destroy view ### *GET* #### Description Retrieve a serialized object of employee. ##### Response ``` { "id": 1, ... } ``` ### *PUT*/*PATCH* #### Description Completely/Partially update an employee object. ##### Request Available fields: * name (`str`) - employee name * last_name (`str`) - employee last name * sex (`enum`) - 0 (Male), 1 (Female) * birth_date (`str`) - datetime in a format `ISO-8601` * email (`str`) - employee email address * phone (`str`) - phone number in E164 format * toque_number (`int`) - employee toque number * available_for_events (`bool`) - flag that responds for availability for events * photo_id (`int`) - image identifier ##### Response Return an employee serialized object E.g.: ``` { "id": 1, ... } ``` ### *DELETE* #### Description Delete an instance of employee ##### Response ``` No content ``` """ serializer_class = serializers.EmployeeBackSerializers queryset = models.Employee.objects.with_back_office_related() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, ) class AdminEmployeeListView(generics.ListAPIView): """ ## Employee list view, where request user is ESTABLISHMENT_ADMINISTRATOR. ### *GET* #### Description Return paginated list of employees. #### Response ``` { "id": 1324, "name": "Alex", "last_name": "Wolf", { ``` """ serializer_class = serializers.AdminEmployeeBackSerializers permission_classes = get_permission_classes(IsEstablishmentAdministrator, ) pagination_class = None def get_queryset(self): user = self.request.user if user.is_anonymous: return None est_ids = models.Establishment.objects.filter( userrole__user=user, userrole__role__role=Role.ESTABLISHMENT_ADMINISTRATOR, ).values_list('id', flat=True) qs = models.Employee.objects.filter(establishments__in=est_ids).distinct().with_back_office_related() if self.request.country_code: qs = qs.filter(establishments__address__city__country__code=self.request.country_code) return qs class RemoveAwardView(generics.DestroyAPIView): """ ## Remove award view. ### *DELETE* #### Description Remove an award from an employee by an employee identifier and an award identifier. ##### Response ``` No content ``` """ lookup_field = 'pk' serializer_class = serializers.EmployeeBackSerializers queryset = models.Employee.objects.with_back_office_related() permission_classes = get_permission_classes() def get_object(self): employee = super().get_object() employee.remove_award(self.kwargs['award_id']) return employee def delete(self, request, *args, **kwargs): instance = self.get_object() return Response(status=status.HTTP_204_NO_CONTENT) class EstablishmentTypeListCreateView(generics.ListCreateAPIView): """ Establishment type list/create view. **GET** ``` Implement getting list of Establishment type. ``` **POST** ``` Implement creating Establishment type ``` """ serializer_class = serializers.EstablishmentTypeBaseSerializer queryset = models.EstablishmentType.objects.select_related('default_image') pagination_class = None permission_classes = get_permission_classes() class EstablishmentTypeRUDView(generics.RetrieveUpdateDestroyAPIView): """ Establishment type retrieve/update/destroy view. **GET** ``` Implement getting Establishment type object by id. ``` **PUT** ``` Implement update Establishment type. ``` **PATCH** ``` Implement partial update Establishment type. ``` **DELETE** ``` Implement deleting Establishment type. ``` """ serializer_class = serializers.EstablishmentTypeBaseSerializer queryset = models.EstablishmentType.objects.select_related('default_image') permission_classes = get_permission_classes() class EstablishmentSubtypeListCreateView(generics.ListCreateAPIView): """ Establishment subtype list/create view. **GET** ``` Implement getting establishment subtype. ``` **POST** ``` Implement create establishment subtype. ``` """ serializer_class = serializers.EstablishmentSubTypeBaseSerializer queryset = models.EstablishmentSubType.objects.select_related('default_image') pagination_class = None permission_classes = get_permission_classes() class EstablishmentSubtypeRUDView(generics.RetrieveUpdateDestroyAPIView): """ Establishment subtype retrieve/update/destroy view. **GET** ``` Implement establishment subtype object getting method. ``` **PUT** ``` Implement establishment subtype update method. ``` **PATCH** ``` Implement establishment subtype partial update method. ``` **DELETE** ``` Implement establishment subtype delete method. ``` """ serializer_class = serializers.EstablishmentSubTypeBaseSerializer queryset = models.EstablishmentSubType.objects.select_related('default_image') permission_classes = get_permission_classes() class EstablishmentGalleryCreateDestroyView(EstablishmentMixinViews, CreateDestroyGalleryViewMixin): """ ## Establishment gallery image Create/Destroy view ### *POST* #### Description Attaching existing **image** by `image identifier` to **establishment** by `establishment slug` in request kwargs. ##### Request ``` No body ``` ##### Response E.g.: ``` No content ``` ### *DELETE* #### Description Delete existing **gallery image** from **establishment** gallery, by `image identifier` and `establishment slug` in request kwargs. **Note**: > Image wouldn't be deleted after all. ##### Request ``` No body ``` ##### Response ``` No content ``` """ lookup_field = 'slug' serializer_class = serializers.EstablishmentBackOfficeGallerySerializer permission_classes = get_permission_classes() def get_object(self): """ Returns the object the view is displaying. """ establishment_qs = self.filter_queryset(self.get_queryset()) establishment = get_object_or_404(establishment_qs, slug=self.kwargs.get('slug')) gallery = get_object_or_404(establishment.establishment_gallery, image_id=self.kwargs.get('image_id')) # May raise a permission denied self.check_object_permissions(self.request, gallery) return gallery class EstablishmentGalleryListView(EstablishmentMixinViews, generics.ListAPIView): """ ## Establishment gallery image list view ### *GET* #### Description Returning paginated list of establishment images by `establishment slug`, with cropped images. ##### Response E.g.: ``` { "count": 1, "next": null, "previous": null, "results": [ { "id": 11, ... } ] } ``` """ lookup_field = 'slug' serializer_class = serializers.ImageBaseSerializer permission_classes = get_permission_classes() def get_object(self): """Override get_object method.""" qs = super(EstablishmentGalleryListView, self).get_queryset() establishment = get_object_or_404(qs, slug=self.kwargs.get('slug')) # May raises a permission denied self.check_object_permissions(self.request, establishment) return establishment def get_queryset(self): """Override get_queryset method.""" return self.get_object().crop_gallery class EstablishmentCompanyListCreateView(EstablishmentMixinViews, generics.ListCreateAPIView): """List|Create establishment company view.""" lookup_field = 'slug' serializer_class = serializers.EstablishmentCompanyListCreateSerializer permission_classes = get_permission_classes() def get_object(self): """Returns the object the view is displaying.""" establishment_qs = super(EstablishmentCompanyListCreateView, self).get_queryset() filtered_qs = self.filter_queryset(establishment_qs) establishment = get_object_or_404(filtered_qs, slug=self.kwargs.get('slug')) # May raise a permission denied self.check_object_permissions(self.request, establishment) return establishment def get_queryset(self): """Overridden get_queryset method.""" return self.get_object().companies.all() class EstablishmentCompanyRUDView(EstablishmentMixinViews, generics.RetrieveUpdateDestroyAPIView): """Create|Retrieve|Update|Destroy establishment company view.""" lookup_field = 'slug' serializer_class = serializers.CompanyBaseSerializer permission_classes = get_permission_classes() def get_object(self): """Returns the object the view is displaying.""" establishment_qs = super(EstablishmentCompanyRUDView, self).get_queryset() filtered_ad_qs = self.filter_queryset(establishment_qs) establishment = get_object_or_404(filtered_ad_qs, slug=self.kwargs.get('slug')) company = get_object_or_404(establishment.companies.all(), pk=self.kwargs.get('company_pk')) # May raise a permission denied self.check_object_permissions(self.request, company) return company class EstablishmentNoteListCreateView(EstablishmentMixinViews, generics.ListCreateAPIView): """Retrieve|Update|Destroy establishment note view.""" lookup_field = 'slug' serializer_class = serializers.EstablishmentNoteListCreateSerializer permission_classes = get_permission_classes( IsEstablishmentAdministrator, IsEstablishmentManager, ) def get_object(self): """Returns the object the view is displaying.""" establishment_qs = super(EstablishmentNoteListCreateView, self).get_queryset() filtered_establishment_qs = self.filter_queryset(establishment_qs) establishment = get_object_or_404(filtered_establishment_qs, slug=self.kwargs.get('slug')) # May raise a permission denied self.check_object_permissions(self.request, establishment) return establishment def get_queryset(self): """Overridden get_queryset method.""" return self.get_object().notes.all() class EstablishmentNoteRUDView(EstablishmentMixinViews, generics.RetrieveUpdateDestroyAPIView): """Create|Retrieve|Update|Destroy establishment note view.""" lookup_field = 'slug' serializer_class = serializers.EstablishmentNoteBaseSerializer permission_classes = get_permission_classes( IsEstablishmentAdministrator, IsEstablishmentManager, ) def get_object(self): """Returns the object the view is displaying.""" establishment_qs = super(EstablishmentNoteRUDView, self).get_queryset() filtered_establishment_qs = self.filter_queryset(establishment_qs) establishment = get_object_or_404(filtered_establishment_qs, slug=self.kwargs.get('slug')) note = get_object_or_404(establishment.notes.all(), pk=self.kwargs['note_pk']) # May raise a permission denied self.check_object_permissions(self.request, note) return note class EstablishmentEmployeeCreateView(generics.CreateAPIView): """ ## Create employee position for establishment ### *POST* #### Description Creating position for an employee for establishment, by `establishment identifier`, `employee identifier` and `position identifier`. ##### Request data Available fields: * from_date - datetime (datetime in a format `ISO-8601`), by default `timezone.now()` * to_date - datetime (datetime in a format `ISO-8601`), by default `null` ##### Response data E.g.: ``` { "id": 47405, "from_date": "2020-02-06T11:01:04.961000Z", "to_date": "2020-02-06T11:01:04.961000Z" } ``` """ serializer_class = serializers.EstablishmentEmployeeCreateSerializer queryset = models.EstablishmentEmployee.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) class EstablishmentEmployeeDeleteView(generics.DestroyAPIView): """ ## Delete employee position for establishment ### *DELETE* #### Description Deleting position for an employee from establishment, by `position identifier`. ##### Response data ``` No content ``` """ queryset = EstablishmentEmployee.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) class EstablishmentPositionListView(generics.ListAPIView): """Establishment positions list view.""" pagination_class = None queryset = models.Position.objects.all() serializer_class = serializers.PositionBackSerializer filter_class = filters.PositionsByEstablishmentFilter permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) def get_queryset(self): return super().get_queryset().order_by('priority') class EstablishmentAdminView(generics.ListAPIView): """ ## List establishment admins ### *GET* #### Description Returning paginated list of establishment administrators by establishment slug. ##### Response ``` { "count": 58, "next": 2, "previous": null, "results": [ { "id": 1, ... } ] } ``` """ serializer_class = serializers.EstablishmentAdminListSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) def get_queryset(self): establishment = get_object_or_404( models.Establishment, slug=self.kwargs['slug']) return User.objects.establishment_admin(establishment).distinct() class EstablishmentGuideCreateDestroyView(generics.GenericAPIView): """Add/Remove establishment from guide.""" establishment_lookup_url_kwarg = 'slug' guide_lookup_url_kwarg = 'guide_id' permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) def get_establishment_queryset(self): """Get Establishment queryset.""" return EstablishmentMixinViews.get_queryset(self) def get_guide_queryset(self): """Get Guide queryset.""" queryset = Guide.objects if hasattr(self, 'request') and hasattr(self.request, 'country_code'): return queryset.by_country_code(self.request.country_code) return queryset.none() def get_establishment(self): queryset = self.get_establishment_queryset() # Perform the lookup filtering. lookup_url_kwarg = getattr(self, 'establishment_lookup_url_kwarg', None) assert lookup_url_kwarg in self.kwargs, ( 'Expected view %s to be called with a URL keyword argument ' 'named "%s". Fix your URL conf, or set the `.lookup_field` ' 'attribute on the view correctly.' % (self.__class__.__name__, lookup_url_kwarg) ) filters = {'klass': queryset, lookup_url_kwarg: self.kwargs.get(lookup_url_kwarg)} obj = get_object_or_404(**filters) # May raise a permission denied self.check_object_permissions(self.request, obj) return obj def get_guide(self): queryset = self.get_guide_queryset() # Perform the lookup filtering. lookup_url_kwarg = getattr(self, 'guide_lookup_url_kwarg', None) assert lookup_url_kwarg in self.kwargs, ( 'Expected view %s to be called with a URL keyword argument ' 'named "%s". Fix your URL conf, or set the `.lookup_field` ' 'attribute on the view correctly.' % (self.__class__.__name__, lookup_url_kwarg) ) obj = get_object_or_404(klass=queryset, id=self.kwargs.get(lookup_url_kwarg)) # May raise a permission denied self.check_object_permissions(self.request, obj) return obj def post(self, request, *args, **kwargs): """Implement GET-method.""" establishment = self.get_establishment() guide = self.get_guide() guide.extend_establishment_guide(establishment.id) return Response(status=status.HTTP_200_OK) def delete(self, request, *args, **kwargs): """Implement DELETE-method.""" establishment = self.get_establishment() guide = self.get_guide() guide.remove_establishment(establishment.id) return Response(status=status.HTTP_204_NO_CONTENT) class MenuDishesListCreateView(generics.ListCreateAPIView): """Menu (dessert, main_course, starter) list create view.""" serializer_class = serializers.MenuDishesSerializer queryset = models.Menu.objects.with_schedule_plates_establishment().dishes().distinct() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) filter_class = filters.MenuDishesBackFilter class MenuDishesRUDView(generics.RetrieveUpdateDestroyAPIView): """Menu (dessert, main_course, starter) RUD view.""" serializer_class = serializers.MenuDishesRUDSerializers queryset = models.Menu.objects.dishes().distinct() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) class MenuGalleryListView(generics.ListAPIView): """Resource for returning gallery for menu for back-office users.""" serializer_class = serializers.ImageBaseSerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) queryset = models.Menu.objects.with_schedule_plates_establishment().with_gallery().dishes() def get_object(self): """Override get_object method.""" qs = super(MenuGalleryListView, self).get_queryset() menu = get_object_or_404(qs, pk=self.kwargs.get('pk')) # May raise a permission denied # self.check_object_permissions(self.request, menu) return menu def get_queryset(self): """Override get_queryset method.""" return self.get_object().crop_gallery class MenuGalleryCreateDestroyView(CreateDestroyGalleryViewMixin): """Resource for a create gallery for menu for back-office users.""" serializer_class = serializers.MenuGallerySerializer permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) def get_queryset(self): """Override get_queryset method.""" qs = models.Menu.objects.with_schedule_plates_establishment().with_gallery().dishes() return qs def create(self, request, *args, **kwargs): _ = super().create(request, *args, **kwargs) news_qs = self.filter_queryset(self.get_queryset()) return response.Response( data=serializers.MenuDishesRUDSerializers(get_object_or_404(news_qs, pk=kwargs.get('pk'))).data ) def get_object(self): """ Returns the object the view is displaying. """ menu_qs = self.filter_queryset(self.get_queryset()) menu = get_object_or_404(menu_qs, pk=self.kwargs.get('pk')) gallery = get_object_or_404(menu.menu_gallery, image_id=self.kwargs.get('image_id')) # May raise a permission denied self.check_object_permissions(self.request, gallery) return gallery class StatusesListView(generics.ListAPIView): """Possible project establishment statuses""" pagination_class = None serializer_class = serializers.EstablishmentStatusesSerializer def get_queryset(self): return None def list(self, request, *args, **kwargs): mutated_for_serializer = [{ 'value': state[0], 'state_translated': state[1], } for state in models.Establishment.STATUS_CHOICES] serializer = self.get_serializer(mutated_for_serializer, many=True) return response.Response(serializer.data) class TeamMemberListView(generics.ListAPIView): """Show team for certain establishment""" pagination_class = None serializer_class = serializers.TeamMemberSerializer queryset = User.objects.all() permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) def get_queryset(self): establishment = get_object_or_404(klass=models.Establishment, pk=self.kwargs['establishment_id']) return super().get_queryset().filter(roles__role=Role.ESTABLISHMENT_ADMINISTRATOR, userrole__establishment=establishment, userrole__state=UserRole.VALIDATED) class TeamMemberDeleteView(generics.DestroyAPIView): """Delete user from team""" permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator ) def get_object(self): return UserRole.objects.get(role__role=Role.ESTABLISHMENT_ADMINISTRATOR, user_id=self.kwargs['user_id'], establishment_id=self.kwargs['establishment_id']) def perform_destroy(self, instance): instance.delete() from account.tasks import team_role_revoked establishment = models.Establishment.objects.get(pk=self.kwargs['establishment_id']) if settings.USE_CELERY: team_role_revoked.delay(self.kwargs['user_id'], self.request.country_code, establishment.name) else: team_role_revoked(self.kwargs['user_id'], self.request.country_code, establishment.name) class EstablishmentAwardCreateAndBind(generics.CreateAPIView, generics.DestroyAPIView): queryset = main_models.Award.objects.with_base_related().all() permission_classes = get_permission_classes() serializer_class = serializers.BackEstablishmentAwardCreateSerializer def _award_list_for_establishment(self, establishment_id: int, status: int) -> Response: awards = main_models.Award.objects.with_base_related().filter( object_id=establishment_id, content_type=ContentType.objects.get_for_model(models.Establishment) ) response_serializer = main_serializers.AwardBaseSerializer(awards, many=True) headers = self.get_success_headers(response_serializer.data) return Response(response_serializer.data, status=status, headers=headers) def create(self, request, *args, **kwargs): """Overridden create method.""" super().create(request, args, kwargs) return self._award_list_for_establishment(kwargs['establishment_id'], status.HTTP_201_CREATED) def delete(self, request, *args, **kwargs): establishment = get_object_or_404(models.Establishment, id=kwargs['establishment_id']) establishment.remove_award(kwargs['award_id']) return self._award_list_for_establishment(kwargs['establishment_id'], status.HTTP_200_OK)