gault-millau/apps/establishment/serializers/back.py
Олег Хаятов 0e7fd39d37 Merge branch 'feature/bo-menus' into 'develop'
Feature/bo menus

See merge request gm/gm-backend!247
2020-01-29 15:54:44 +00:00

645 lines
19 KiB
Python

from functools import lru_cache
from pprint import pprint
from django.db.models import F
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from account.serializers.common import UserShortSerializer
from establishment import models, serializers as model_serializers
from establishment.models import ContactEmail, ContactPhone, EstablishmentEmployee
from establishment.serializers import MenuDishSerializer
from gallery.models import Image
from location.models import Address
from location.serializers import AddressDetailSerializer, TranslatedField
from main.models import Currency
from main.serializers import AwardSerializer
from utils.decorators import with_base_attributes
from utils.serializers import ImageBaseSerializer, ProjectModelSerializer, TimeZoneChoiceField
def phones_handler(phones_list, establishment):
"""
create or update phones for establishment
"""
ContactPhone.objects.filter(establishment=establishment).delete()
for new_phone in phones_list:
ContactPhone.objects.create(establishment=establishment, phone=new_phone)
def emails_handler(emails_list, establishment):
"""
create or update emails for establishment
"""
ContactEmail.objects.filter(establishment=establishment).delete()
for new_email in emails_list:
ContactEmail.objects.create(establishment=establishment, email=new_email)
class EstablishmentListCreateSerializer(model_serializers.EstablishmentBaseSerializer):
"""Establishment create serializer"""
type_id = serializers.PrimaryKeyRelatedField(
source='establishment_type',
queryset=models.EstablishmentType.objects.all(),
write_only=True
)
address_id = serializers.PrimaryKeyRelatedField(
source='address',
queryset=models.Address.objects.all(),
write_only=True
)
socials = model_serializers.SocialNetworkRelatedSerializers(
read_only=True,
many=True,
)
type = model_serializers.EstablishmentTypeBaseSerializer(
source='establishment_type',
read_only=True,
)
tz = TimeZoneChoiceField()
phones = serializers.ListField(
source='contact_phones',
allow_null=True,
allow_empty=True,
child=serializers.CharField(max_length=128),
required=False,
)
emails = serializers.ListField(
source='contact_emails',
allow_null=True,
allow_empty=True,
child=serializers.CharField(max_length=128),
required=False,
)
class Meta:
model = models.Establishment
fields = [
'id',
'name',
'transliterated_name',
'index_name',
'website',
'phones',
'emails',
'price_level',
'toque_number',
'type_id',
'type',
'socials',
'image_url',
'slug',
# TODO: check in admin filters
'is_publish',
'guestonline_id',
'lastable_id',
'tags',
'tz',
'address_id',
'western_name',
]
def create(self, validated_data):
phones_list = []
if 'contact_phones' in validated_data:
phones_list = validated_data.pop('contact_phones')
emails_list = []
if 'contact_emails' in validated_data:
emails_list = validated_data.pop('contact_emails')
instance = super().create(validated_data)
phones_handler(phones_list, instance)
emails_handler(emails_list, instance)
return instance
class EstablishmentPositionListSerializer(model_serializers.EstablishmentBaseSerializer):
"""Establishment position serializer"""
class Meta:
model = models.Establishment
fields = [
'id',
'name',
'transliterated_name',
'index_name',
]
class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
"""Establishment create serializer"""
type_id = serializers.PrimaryKeyRelatedField(
source='establishment_type',
queryset=models.EstablishmentType.objects.all(), write_only=True
)
address = AddressDetailSerializer(read_only=True)
emails = serializers.ListField(
source='contact_emails',
allow_null=True,
allow_empty=True,
child=serializers.CharField(max_length=128),
required=False,
)
socials = model_serializers.SocialNetworkRelatedSerializers(read_only=False,
many=True, )
type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type')
phones = serializers.ListField(
source='contact_phones',
allow_null=True,
allow_empty=True,
child=serializers.CharField(max_length=128),
required=False,
)
class Meta:
model = models.Establishment
fields = [
'id',
'slug',
'western_name',
'name',
'website',
'phones',
'emails',
'price_level',
'toque_number',
'type_id',
'type',
'socials',
'image_url',
# TODO: check in admin filters
'is_publish',
'address',
'transportation',
'tags',
]
def update(self, instance, validated_data):
phones_list = []
if 'contact_phones' in validated_data:
phones_list = validated_data.pop('contact_phones')
emails_list = []
if 'contact_emails' in validated_data:
emails_list = validated_data.pop('contact_emails')
instance = super().update(instance, validated_data)
phones_handler(phones_list, instance)
emails_handler(emails_list, instance)
return instance
class SocialChoiceSerializers(serializers.ModelSerializer):
"""SocialChoice serializers."""
class Meta:
model = models.SocialChoice
fields = '__all__'
class SocialNetworkSerializers(serializers.ModelSerializer):
"""Social network serializers."""
class Meta:
model = models.SocialNetwork
fields = [
'id',
'establishment',
'network',
'url',
]
class PlatesSerializers(model_serializers.PlateSerializer):
"""Plates serializers."""
currency_id = serializers.PrimaryKeyRelatedField(
source='currency',
queryset=Currency.objects.all(), write_only=True
)
class Meta:
"""Meta class."""
model = models.Plate
fields = model_serializers.PlateSerializer.Meta.fields + [
'name',
'currency_id',
'menu'
]
class ContactPhoneBackSerializers(model_serializers.PlateSerializer):
"""ContactPhone serializers."""
class Meta:
model = models.ContactPhone
fields = [
'id',
'establishment',
'phone'
]
class ContactEmailBackSerializers(model_serializers.PlateSerializer):
"""ContactEmail serializers."""
class Meta:
model = models.ContactEmail
fields = [
'id',
'establishment',
'email'
]
class PositionBackSerializer(serializers.ModelSerializer):
"""Position Back serializer."""
name_translated = TranslatedField()
class Meta:
model = models.Position
fields = [
'id',
'name_translated',
'priority',
'index_name',
]
# TODO: test decorator
@with_base_attributes
class EmployeeBackSerializers(serializers.ModelSerializer):
"""Employee serializers."""
public_mark = serializers.SerializerMethodField()
positions = serializers.SerializerMethodField()
establishment = serializers.SerializerMethodField()
awards = AwardSerializer(many=True, read_only=True)
toque_number = serializers.SerializerMethodField()
photo = ImageBaseSerializer(source='crop_image', read_only=True)
photo_id = serializers.PrimaryKeyRelatedField(source='photo', write_only=True, required=False,
queryset=Image.objects.all(), allow_null=True)
@staticmethod
@lru_cache(maxsize=32)
def get_qs(obj):
return obj.establishmentemployee_set.actual().annotate(
public_mark=F('establishment__public_mark'),
est_id=F('establishment__id'),
est_slug=F('establishment__slug'),
toque_number=F('establishment__toque_number'),
).order_by('-from_date').first()
def get_public_mark(self, obj):
"""Get last list actual public_mark"""
if hasattr(obj, 'prefetched_establishment_employee'):
return obj.prefetched_establishment_employee[0].establishment.public_mark if len(
obj.prefetched_establishment_employee) else None
qs = self.get_qs(obj)
if qs:
return qs.public_mark
return None
def get_toque_number(self, obj):
if hasattr(obj, 'prefetched_establishment_employee'):
return obj.prefetched_establishment_employee[0].establishment.toque_number if len(
obj.prefetched_establishment_employee) else None
qs = self.get_qs(obj)
if qs:
return qs.toque_number
return None
def get_positions(self, obj):
"""Get last list actual positions"""
if hasattr(obj, 'prefetched_establishment_employee'):
if not len(obj.prefetched_establishment_employee):
return []
return [PositionBackSerializer(ee.position).data for ee in obj.prefetched_establishment_employee]
est_id = self.get_qs(obj)
if not est_id:
return None
qs = obj.establishmentemployee_set.actual() \
.filter(establishment_id=est_id.establishment_id) \
.prefetch_related('position').values('position')
positions = models.Position.objects.filter(id__in=[q['position'] for q in qs])
return [PositionBackSerializer(p).data for p in positions]
def get_establishment(self, obj):
"""Get last actual establishment"""
if hasattr(obj, 'prefetched_establishment_employee'):
return {
'id': obj.prefetched_establishment_employee[0].establishment.pk,
'slug': obj.prefetched_establishment_employee[0].establishment.slug,
} if len(obj.prefetched_establishment_employee) else None
est = self.get_qs(obj)
if not est:
return None
return {
"id": est.est_id,
"slug": est.est_slug
}
class Meta:
model = models.Employee
fields = [
'id',
'name',
'last_name',
'user',
'public_mark',
'positions',
'awards',
'establishment',
'sex',
'birth_date',
'email',
'phone',
'toque_number',
'available_for_events',
'photo',
'photo_id',
]
class EstablishmentEmployeeBackSerializer(serializers.ModelSerializer):
"""Establishment Employee serializer."""
employee = EmployeeBackSerializers()
position = PositionBackSerializer()
class Meta:
model = models.EstablishmentEmployee
fields = [
'id',
'employee',
'from_date',
'to_date',
'position',
'status',
]
class EstEmployeeBackSerializer(EmployeeBackSerializers):
@property
def request_kwargs(self):
"""Get url kwargs from request."""
return self.context.get('request').parser_context.get('kwargs')
def get_positions(self, obj):
establishment_id = self.request_kwargs.get('establishment_id')
es_emp = EstablishmentEmployee.objects.filter(
employee=obj,
establishment_id=establishment_id,
).distinct().order_by('position_id')
result = []
for item in es_emp:
result.append({
'id': item.id,
'from_date': item.from_date,
'to_date': item.to_date,
'status': item.status,
'position_id': item.position_id,
'position_priority': item.position.priority,
'position_index_name': item.position.index_name,
'position_name_translated': item.position.name_translated,
})
return result
class Meta:
model = models.Employee
fields = [
'id',
'name',
'last_name',
'user',
'public_mark',
'positions',
'awards',
'sex',
'birth_date',
'email',
'phone',
'toque_number',
'available_for_events',
'photo',
]
class EstablishmentBackOfficeGallerySerializer(serializers.ModelSerializer):
"""Serializer class for model EstablishmentGallery."""
class Meta:
"""Meta class"""
model = models.EstablishmentGallery
fields = [
'id',
'is_main',
]
@property
def request_kwargs(self):
"""Get url kwargs from request."""
return self.context.get('request').parser_context.get('kwargs')
def validate(self, attrs):
"""Override validate method."""
establishment_pk = self.request_kwargs.get('pk')
establishment_slug = self.request_kwargs.get('slug')
search_kwargs = {'pk': establishment_pk} if establishment_pk else {'slug': establishment_slug}
image_id = self.request_kwargs.get('image_id')
establishment_qs = models.Establishment.objects.filter(**search_kwargs)
image_qs = Image.objects.filter(id=image_id)
if not establishment_qs.exists():
raise serializers.ValidationError({'detail': _('Establishment not found')})
if not image_qs.exists():
raise serializers.ValidationError({'detail': _('Image not found')})
establishment = establishment_qs.first()
image = image_qs.first()
if image in establishment.gallery.all():
raise serializers.ValidationError({'detail': _('Image is already added.')})
attrs['establishment'] = establishment
attrs['image'] = image
return attrs
class EstablishmentCompanyListCreateSerializer(model_serializers.CompanyBaseSerializer):
"""Serializer for linking page w/ advertisement."""
class Meta(model_serializers.CompanyBaseSerializer.Meta):
"""Meta class."""
model_serializers.CompanyBaseSerializer.Meta.extra_kwargs.update({
'establishment': {'required': False}
})
def create(self, validated_data):
"""Overridden create method."""
validated_data['establishment'] = self.context.get('view').get_object()
return super().create(validated_data)
class EstablishmentNoteBaseSerializer(serializers.ModelSerializer):
"""Serializer for model EstablishmentNote."""
user_detail = UserShortSerializer(read_only=True, source='user')
class Meta:
"""Meta class."""
model = models.EstablishmentNote
fields = [
'id',
'created',
'modified',
'text',
'user',
'user_detail',
'establishment',
]
extra_kwargs = {
'created': {'read_only': True},
'modified': {'read_only': True},
'establishment': {'required': False, 'write_only': True},
'user': {'required': False, 'write_only': True},
}
@property
def serializer_view(self):
"""Return view instance."""
return self.context.get('view')
class EstablishmentNoteListCreateSerializer(EstablishmentNoteBaseSerializer):
"""Serializer for List|Create action for model EstablishmentNote."""
def create(self, validated_data):
"""Overridden create method."""
validated_data['user'] = self.user
validated_data['establishment'] = self.establishment
return super().create(validated_data)
@property
def user(self):
"""Return user instance from view."""
if self.serializer_view:
return self.serializer_view.request.user
@property
def establishment(self):
"""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'
]
class EstablishmentEmployeePositionsSerializer(serializers.ModelSerializer):
"""Establishments from employee serializer"""
restaurant_name = serializers.CharField(read_only=True, source='establishment.name')
position = PositionBackSerializer(read_only=True)
state = serializers.CharField(read_only=True, source='status')
start = serializers.DateTimeField(read_only=True, source='from_date')
end = serializers.DateTimeField(read_only=True, source='to_date')
class Meta:
model = models.EstablishmentEmployee
fields = [
'restaurant_name',
'position',
'state',
'start',
'end',
]
class MenuDishesSerializer(ProjectModelSerializer):
"""for dessert, main_course and starter category"""
establishment_id = serializers.PrimaryKeyRelatedField(read_only=True)
establishment_slug = serializers.CharField(read_only=True, source='establishment.slug')
dishes = MenuDishSerializer(many=True, read_only=True)
class Meta:
model = models.Menu
fields = [
'id',
'establishment_id',
'establishment_slug',
'dishes',
]
class MenuDishesCreateSerializer(ProjectModelSerializer):
"""Menu dishes create serializer"""
menu_id = serializers.IntegerField(write_only=True)
class Meta:
model = models.MenuDish
fields = [
'id',
'name',
'category',
'price',
'signature',
'menu_id'
]
def create(self, validated_data):
menu_id = validated_data.pop('menu_id')
menu = get_object_or_404(models.Menu, pk=menu_id)
instance = models.MenuDish.objects.create(**validated_data)
menu.dishes.add(instance)
return instance
class MenuDishesRUDSerializers(ProjectModelSerializer):
"""for dessert, main_course and starter category"""
establishment_id = serializers.PrimaryKeyRelatedField(queryset=models.Establishment.objects.all())
establishment_slug = serializers.CharField(read_only=True, source='establishment.slug')
dishes = MenuDishSerializer(many=True, read_only=True)
class Meta:
model = models.Menu
fields = [
'id',
'establishment_id',
'establishment_slug',
'dishes',
]