gault-millau/apps/establishment/views/back.py
2020-02-10 15:14:01 +03:00

1732 lines
50 KiB
Python

"""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.
**GET**
```
Implement getting SocialChoice list.
```
**POST**
```
Implement creating SocialChoice.
```
"""
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.
**GET**
```
Implement getting SocialChoice object.
```
**PUT**
```
Implement updating SocialChoice.
```
**PATCH**
```
Implement partial updating SocialChoice.
```
**DELETE**
```
Implement deleting SocialChoice.
```
"""
serializer_class = serializers.SocialChoiceSerializers
queryset = models.SocialChoice.objects.all()
permission_classes = get_permission_classes(
IsEstablishmentManager,
IsEstablishmentAdministrator,
)
class SocialListCreateView(generics.ListCreateAPIView):
"""
Social list create view.
**GET**
```
Implement getting Social list.
```
**POST**
```
Implement creating Social.
```
"""
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.
**GET**
```
Implement getting Social object.
```
**PUT**
```
Implement updating Social.
```
**PATCH**
```
Implement partial updating Social.
```
**DELETE**
```
Implement deleting Social.
```
"""
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.
**GET**
```
Implement getting Phone list.
```
**POST**
```
Implement creating Phone.
```
"""
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.
**GET**
```
Implement getting Phone object.
```
**PUT**
```
Implement updating Phone.
```
**PATCH**
```
Implement partial updating Phone.
```
**DELETE**
```
Implement deleting Phone.
```
"""
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):
"""
## List/Create view
### *GET*
#### Description
Return paginated list of establishment notes by `establishment slug`
##### Response
E.g.:
```
{
"count": 58,
"next": 2,
"previous": null,
"results": [
{
"id": 1,
...
}
]
}
```
### *POST*
#### Description
Create new note for establishment by `establishment slug`
##### Request
Required
* text (`str`) - text of note
##### Response
E.g.:
```
{
"id": 1,
...
}
```
"""
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):
"""An overridden get_queryset method."""
return self.get_object().notes.all()
class EstablishmentNoteRUDView(EstablishmentMixinViews,
generics.RetrieveUpdateDestroyAPIView):
"""
## Retrieve/Update/Destroy view
### *GET*
#### Description
Return paginated list of establishment notes by `establishment slug`
##### Response
E.g.:
```
{
"count": 58,
"next": 2,
"previous": null,
"results": [
{
"id": 1,
...
}
]
}
```
### *PUT*/*PATCH*
#### Description
Completely/Partially update a note object by an identifier.
##### Request
Available
* text (`str`) - text of note
##### Response
E.g.:
```
{
"id": 1,
...
}
```
### *DELETE*
#### Description
Delete establishment note by `establishment slug`
##### Response
E.g.:
```
No content
```
"""
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 a 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)