1050 lines
34 KiB
Python
1050 lines
34 KiB
Python
from datetime import datetime
|
|
from functools import lru_cache
|
|
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.db.models import F
|
|
from django.shortcuts import get_object_or_404
|
|
from django.utils.translation import gettext_lazy as _
|
|
from phonenumber_field.serializerfields import PhoneNumberField
|
|
from rest_framework import serializers
|
|
from slugify import slugify
|
|
|
|
from account import models as account_models
|
|
from account.models import Role
|
|
from account.serializers.common import UserShortSerializer
|
|
from collection.models import Guide
|
|
from establishment import models, serializers as model_serializers
|
|
from establishment.models import ContactEmail, ContactPhone, EstablishmentEmployee
|
|
from establishment.serializers.common import ContactPhonesSerializer
|
|
from review.serializers.common import ReviewBaseSerializer
|
|
from gallery.models import Image
|
|
from location.serializers import AddressDetailSerializer, TranslatedField, AddressBaseSerializer, \
|
|
AddressEstablishmentSerializer
|
|
from main import models as main_models
|
|
from main.models import Currency
|
|
from main.serializers import AwardSerializer
|
|
from review.serializers import ReviewBaseSerializer, User
|
|
from tag.serializers import TagBaseSerializer
|
|
from utils.decorators import with_base_attributes
|
|
from utils.methods import string_random
|
|
from utils.serializers import ImageBaseSerializer, ProjectModelSerializer, TimeZoneChoiceField, \
|
|
PhoneMixinSerializer
|
|
|
|
|
|
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,
|
|
required=False,
|
|
)
|
|
address = AddressEstablishmentSerializer(allow_null=True)
|
|
transliterated_name = serializers.CharField(
|
|
required=False, allow_null=True, allow_blank=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=PhoneNumberField(),
|
|
required=False,
|
|
write_only=True,
|
|
)
|
|
contact_phones = ContactPhonesSerializer(source='phones', read_only=True, many=True)
|
|
emails = serializers.ListField(
|
|
source='contact_emails',
|
|
allow_null=True,
|
|
allow_empty=True,
|
|
child=serializers.CharField(max_length=128),
|
|
required=False,
|
|
)
|
|
subtypes = model_serializers.EstablishmentSubTypeBaseSerializer(source='establishment_subtypes',
|
|
read_only=True, many=True)
|
|
reviews = ReviewBaseSerializer(allow_null=True, read_only=True, many=True)
|
|
restaurant_category = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
|
restaurant_cuisine = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
|
artisan_category = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
|
distillery_type = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
|
food_producer = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
|
vintage_year = serializers.IntegerField(read_only=True, allow_null=True)
|
|
|
|
class Meta(model_serializers.EstablishmentBaseSerializer.Meta):
|
|
fields = [
|
|
'id',
|
|
'name',
|
|
'transliterated_name',
|
|
'index_name',
|
|
'website',
|
|
'phones',
|
|
'contact_phones',
|
|
'toque_number',
|
|
'public_mark',
|
|
'emails',
|
|
'price_level',
|
|
'toque_number',
|
|
'type_id',
|
|
'type',
|
|
'subtypes',
|
|
'socials',
|
|
'image_url',
|
|
'slug',
|
|
'facebook',
|
|
'twitter',
|
|
'instagram',
|
|
# TODO: check in admin filters
|
|
'is_publish',
|
|
'guestonline_id',
|
|
'lastable_id',
|
|
'tags',
|
|
'tz',
|
|
'address',
|
|
'address_id',
|
|
'status',
|
|
'status_display',
|
|
'restaurant_category',
|
|
'restaurant_cuisine',
|
|
'artisan_category',
|
|
'distillery_type',
|
|
'food_producer',
|
|
'reviews',
|
|
'vintage_year',
|
|
]
|
|
|
|
def to_representation(self, instance):
|
|
data = super(EstablishmentListCreateSerializer, self).to_representation(instance)
|
|
data['phones'] = data.pop('contact_phones', None)
|
|
return data
|
|
|
|
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')
|
|
|
|
index_name = validated_data.get('index_name')
|
|
if 'slug' not in validated_data and index_name:
|
|
slug = slugify(
|
|
index_name,
|
|
word_boundary=True
|
|
)
|
|
while models.Establishment.objects.filter(slug=slug).exists():
|
|
slug = slugify(
|
|
f'{index_name} {string_random()}',
|
|
word_boundary=True
|
|
)
|
|
validated_data['slug'] = slug
|
|
|
|
if 'address' in validated_data:
|
|
address = models.Address(**validated_data.pop('address'))
|
|
address.save()
|
|
validated_data['address_id'] = address.id
|
|
|
|
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=True,
|
|
many=True, )
|
|
subtypes = model_serializers.EstablishmentSubTypeBaseSerializer(source='establishment_subtypes',
|
|
read_only=True, many=True)
|
|
type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True)
|
|
|
|
phones = serializers.ListField(
|
|
source='contact_phones',
|
|
allow_null=True,
|
|
allow_empty=True,
|
|
child=PhoneNumberField(),
|
|
required=False,
|
|
write_only=True,
|
|
)
|
|
|
|
contact_phones = ContactPhonesSerializer(source='phones', read_only=True, many=True)
|
|
|
|
last_review = ReviewBaseSerializer(read_only=True)
|
|
|
|
must_of_the_week = serializers.BooleanField(required=False, )
|
|
|
|
class Meta(model_serializers.EstablishmentBaseSerializer.Meta):
|
|
fields = [
|
|
'id',
|
|
'slug',
|
|
'transliterated_name',
|
|
'name',
|
|
'index_name',
|
|
'website',
|
|
'phones',
|
|
'contact_phones',
|
|
'emails',
|
|
'price_level',
|
|
'toque_number',
|
|
'type_id',
|
|
'type',
|
|
'subtypes',
|
|
'socials',
|
|
'image_url',
|
|
'facebook',
|
|
'twitter',
|
|
'instagram',
|
|
# TODO: check in admin filters
|
|
'is_publish',
|
|
'address',
|
|
'transportation',
|
|
'tags',
|
|
'status',
|
|
'status_display',
|
|
'last_review',
|
|
'must_of_the_week',
|
|
'last_update_by_gm',
|
|
'last_update_by_manager',
|
|
'public_mark',
|
|
]
|
|
|
|
def to_representation(self, instance):
|
|
data = super(EstablishmentRUDSerializer, self).to_representation(instance)
|
|
data['phones'] = data.pop('contact_phones', None)
|
|
return data
|
|
|
|
def update(self, instance: models.Establishment, 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')
|
|
|
|
request = self.context.get('request')
|
|
if request and hasattr(request, 'user'):
|
|
user = request.user
|
|
|
|
if isinstance(user, User):
|
|
is_by_manager = user.userrole_set.filter(
|
|
pk=user.pk,
|
|
role__in=(
|
|
Role.ESTABLISHMENT_MANAGER,
|
|
Role.ESTABLISHMENT_ADMINISTRATOR,
|
|
Role.COUNTRY_ADMIN
|
|
)
|
|
).exists()
|
|
|
|
if is_by_manager:
|
|
instance.last_update_by_manager = datetime.now()
|
|
else:
|
|
''' by gm. '''
|
|
instance.last_update_by_gm = datetime.now()
|
|
|
|
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(PhoneMixinSerializer, serializers.ModelSerializer):
|
|
"""ContactPhone serializers."""
|
|
|
|
class Meta:
|
|
model = models.ContactPhone
|
|
fields = [
|
|
'id',
|
|
'establishment',
|
|
'phone',
|
|
'country_calling_code',
|
|
'national_calling_number',
|
|
]
|
|
extra_kwarg = {
|
|
'phone': {'write_only': True}
|
|
}
|
|
|
|
|
|
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',
|
|
]
|
|
|
|
|
|
class AdminEmployeeBackSerializers(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
model = models.Employee
|
|
fields = [
|
|
'id',
|
|
'name',
|
|
'last_name',
|
|
]
|
|
|
|
|
|
# TODO: test decorator
|
|
@with_base_attributes
|
|
class EmployeeBackSerializers(PhoneMixinSerializer, 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().only(
|
|
'establishment',
|
|
'from_date',
|
|
).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',
|
|
'country_calling_code',
|
|
'national_calling_number',
|
|
'toque_number',
|
|
'available_for_events',
|
|
'photo',
|
|
'photo_id',
|
|
]
|
|
extra_kwargs = {
|
|
'phone': {'write_only': True},
|
|
'available_for_events': {'required': False}
|
|
}
|
|
|
|
|
|
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')
|
|
establishment = self.context['view'].kwargs['establishment_instance']
|
|
establishment_type = self.context['view'].kwargs['establishment_instance_type']
|
|
establishment_subtypes = self.context['view'].kwargs['establishment_instance_subtypes']
|
|
es_emp = EstablishmentEmployee.objects.filter(
|
|
employee=obj,
|
|
establishment_id=establishment_id,
|
|
).distinct().order_by('from_date').prefetch_related('position', 'position__establishment_type',
|
|
'position__establishment_subtype')
|
|
result = []
|
|
for item in es_emp:
|
|
if item.position.establishment_type == establishment_type or \
|
|
item.position.establishment_subtype in establishment_subtypes or \
|
|
(item.position.establishment_subtype is None and item.position.establishment_type is None):
|
|
# show only relevant for current establishment positions
|
|
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',
|
|
'country_calling_code',
|
|
'national_calling_number',
|
|
'toque_number',
|
|
'available_for_events',
|
|
'photo',
|
|
'photo_id',
|
|
]
|
|
|
|
|
|
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 EstablishmentGuideSerializer(serializers.ModelSerializer):
|
|
"""Serializer for model Guide. """
|
|
|
|
class Meta:
|
|
"""Meta class."""
|
|
model = Guide
|
|
fields = [
|
|
'id',
|
|
]
|
|
|
|
|
|
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 _PlateSerializer(ProjectModelSerializer):
|
|
name_translated = TranslatedField()
|
|
|
|
class Meta:
|
|
model = models.Plate
|
|
fields = [
|
|
'name_translated',
|
|
'price',
|
|
]
|
|
|
|
|
|
class _MenuUploadsSerializer(serializers.Serializer):
|
|
id = serializers.IntegerField()
|
|
title = serializers.CharField()
|
|
original_url = serializers.URLField()
|
|
|
|
|
|
class MenuDishesSerializer(ProjectModelSerializer):
|
|
"""for dessert, main_course and starter category"""
|
|
|
|
plates = _PlateSerializer(read_only=True, many=True, source='plate_set', allow_null=True)
|
|
category_translated = serializers.CharField(read_only=True)
|
|
last_update = serializers.DateTimeField(source='created')
|
|
gallery = ImageBaseSerializer(read_only=True, source='crop_gallery', many=True)
|
|
|
|
class Meta:
|
|
model = models.Menu
|
|
fields = [
|
|
'id',
|
|
'category',
|
|
'category_translated',
|
|
'establishment',
|
|
'is_drinks_included',
|
|
'schedule',
|
|
'plates',
|
|
'last_update',
|
|
'gallery',
|
|
]
|
|
|
|
|
|
class MenuDishesRUDSerializers(ProjectModelSerializer):
|
|
"""for dessert, main_course and starter category"""
|
|
|
|
plates = _PlateSerializer(read_only=True, many=True, source='plate_set', allow_null=True)
|
|
gallery = ImageBaseSerializer(read_only=True, source='crop_gallery', many=True)
|
|
|
|
class Meta:
|
|
model = models.Menu
|
|
fields = [
|
|
'id',
|
|
'category',
|
|
'plates',
|
|
'establishment',
|
|
'is_drinks_included',
|
|
'schedule',
|
|
'gallery',
|
|
]
|
|
|
|
|
|
class MenuGallerySerializer(serializers.ModelSerializer):
|
|
"""Serializer class for model MenuGallery."""
|
|
|
|
class Meta:
|
|
"""Meta class"""
|
|
|
|
model = models.MenuGallery
|
|
fields = [
|
|
'id',
|
|
'is_main',
|
|
]
|
|
|
|
@property
|
|
def request_kwargs(self):
|
|
"""Get url kwargs from request."""
|
|
return self.context.get('request').parser_context.get('kwargs')
|
|
|
|
def create(self, validated_data):
|
|
menu_pk = self.request_kwargs.get('pk')
|
|
image_id = self.request_kwargs.get('image_id')
|
|
qs = models.MenuGallery.objects.filter(image_id=image_id, menu_id=menu_pk)
|
|
instance = qs.first()
|
|
if instance:
|
|
qs.update(**validated_data)
|
|
return instance
|
|
return super().create(validated_data)
|
|
|
|
def validate(self, attrs):
|
|
"""Override validate method."""
|
|
menu_pk = self.request_kwargs.get('pk')
|
|
image_id = self.request_kwargs.get('image_id')
|
|
|
|
menu_qs = models.Menu.objects.filter(pk=menu_pk)
|
|
image_qs = Image.objects.filter(id=image_id)
|
|
|
|
if not menu_qs.exists():
|
|
raise serializers.ValidationError({'detail': _('Menu not found')})
|
|
if not image_qs.exists():
|
|
raise serializers.ValidationError({'detail': _('Image not found')})
|
|
|
|
menu = menu_qs.first()
|
|
image = image_qs.first()
|
|
|
|
attrs['menu'] = menu
|
|
attrs['image'] = image
|
|
|
|
return attrs
|
|
|
|
|
|
class MenuFilesSerializers(ProjectModelSerializer):
|
|
type = serializers.CharField(read_only=True)
|
|
|
|
class Meta:
|
|
model = models.MenuFiles
|
|
fields = [
|
|
'id',
|
|
'name',
|
|
'type',
|
|
'file',
|
|
]
|
|
|
|
def create(self, validated_data):
|
|
instance = models.MenuFiles.objects.create(**validated_data)
|
|
return instance
|
|
|
|
def validate(self, attrs):
|
|
extension = attrs['file'].name.split('.')[-1]
|
|
attrs['type'] = 'image' if extension in ('jpg', 'jpeg', 'png') else 'file'
|
|
if 'name' not in attrs or not attrs['name']:
|
|
attrs['name'] = attrs['file'].name
|
|
return attrs
|
|
|
|
|
|
class MenuBackOfficeSerializer(serializers.ModelSerializer):
|
|
name = serializers.CharField(source='category_translated')
|
|
drinks_included = serializers.BooleanField(source='is_drinks_included')
|
|
establishment_id = serializers.IntegerField(source='establishment.id')
|
|
establishment_slug = serializers.CharField(source='establishment.slug', read_only=True)
|
|
uploads = MenuFilesSerializers(many=True, read_only=True)
|
|
|
|
class Meta:
|
|
model = models.Menu
|
|
fields = [
|
|
'id',
|
|
'type',
|
|
'name',
|
|
'establishment_id',
|
|
'establishment_slug',
|
|
'price',
|
|
'drinks_included',
|
|
'diner',
|
|
'lunch',
|
|
'last_update',
|
|
'uploads',
|
|
'uploads_ids',
|
|
]
|
|
extra_kwargs = {
|
|
'last_update': {'read_only': True},
|
|
'uploads_ids': {'write_only': True, 'source': 'uploads', 'required': True},
|
|
}
|
|
|
|
def validate(self, attrs):
|
|
attrs['category'] = {'en-GB': attrs.pop('category_translated')}
|
|
return attrs
|
|
|
|
def update(self, instance, validated_data):
|
|
uploaded_files_ids = validated_data.pop('uploads')
|
|
establishment_kwargs = validated_data.pop('establishment')
|
|
establishment = get_object_or_404(models.Establishment, **establishment_kwargs)
|
|
validated_data['establishment'] = establishment
|
|
instance = super().update(instance, validated_data)
|
|
instance.uploads.set(uploaded_files_ids)
|
|
return instance
|
|
|
|
def create(self, validated_data):
|
|
uploaded_files_ids = validated_data.pop('uploads')
|
|
establishment_kwargs = validated_data.pop('establishment')
|
|
establishment = get_object_or_404(models.Establishment, **establishment_kwargs)
|
|
validated_data['establishment'] = establishment
|
|
instance = models.Menu.objects.create(**validated_data)
|
|
instance.uploads.set(uploaded_files_ids)
|
|
return instance
|
|
|
|
|
|
class EstablishmentBackOfficeWineSerializer(serializers.ModelSerializer):
|
|
establishment_id = serializers.PrimaryKeyRelatedField(
|
|
source='establishment',
|
|
queryset=models.Establishment.objects.all(),
|
|
write_only=True
|
|
)
|
|
"""BackOffice wine serializer"""
|
|
|
|
class Meta:
|
|
model = models.EstablishmentBackOfficeWine
|
|
fields = (
|
|
'id',
|
|
'bottles',
|
|
'price_from',
|
|
'price_to',
|
|
'price_from_for_one',
|
|
'price_to_for_one',
|
|
'is_glass',
|
|
'establishment_id',
|
|
)
|
|
|
|
|
|
class CardAndWinesPlatesSerializer(serializers.ModelSerializer):
|
|
"""Serializer for card&wines backoffice section"""
|
|
|
|
type = serializers.CharField(source='menu.type')
|
|
|
|
class Meta:
|
|
model = models.Plate
|
|
fields = (
|
|
'id',
|
|
'name',
|
|
'is_signature_plate',
|
|
'price',
|
|
'type',
|
|
)
|
|
extra_kwargs = {
|
|
}
|
|
|
|
def create(self, validated_data):
|
|
establishment = get_object_or_404(models.Establishment, pk=self.context['view'].kwargs['establishment_id'])
|
|
menu_type = validated_data.pop('menu')['type']
|
|
if menu_type not in models.Menu.VALID_CARD_AND_WINES_CHOICES:
|
|
raise serializers.ValidationError({
|
|
'detail':
|
|
f'Incorrect type: {menu_type}. Valid types: [{", ".join(models.Menu.VALID_CARD_AND_WINES_CHOICES)}]'
|
|
})
|
|
menu_to_bind = establishment.menu_set.filter(type=menu_type).first()
|
|
if menu_to_bind is None:
|
|
menu_to_bind = models.Menu.objects.create(type=menu_type, category={'en-GB': menu_type},
|
|
establishment=establishment)
|
|
validated_data.update({'menu': menu_to_bind})
|
|
return super().create(validated_data)
|
|
|
|
def update(self, instance, validated_data):
|
|
menu_type = validated_data.pop('menu')['type']
|
|
if menu_type not in models.Menu.VALID_CARD_AND_WINES_CHOICES:
|
|
raise serializers.ValidationError({
|
|
'detail':
|
|
f'Incorrect type: {menu_type}. Valid types: [{", ".join(models.Menu.VALID_CARD_AND_WINES_CHOICES)}]'
|
|
})
|
|
if instance.menu.type != menu_type: # type changed
|
|
establishment = instance.menu.establishment
|
|
menu_to_bind = establishment.menu_set.filter(type=menu_type).first()
|
|
if menu_to_bind is None:
|
|
menu_to_bind = models.Menu.objects.create(type=menu_type, category={'en-GB': menu_type},
|
|
establishment=establishment)
|
|
validated_data.update({'menu': menu_to_bind})
|
|
return super().update(instance, validated_data)
|
|
|
|
|
|
class CardAndWinesSerializer(serializers.ModelSerializer):
|
|
"""Serializer to show menus(not formulas) with dishes for certain establishment"""
|
|
|
|
wine = EstablishmentBackOfficeWineSerializer(allow_null=True, read_only=True, source='back_office_wine')
|
|
dishes = CardAndWinesPlatesSerializer(many=True, source='card_and_wine_plates')
|
|
|
|
class Meta:
|
|
model = models.Establishment
|
|
fields = (
|
|
'wine',
|
|
'dishes',
|
|
)
|
|
|
|
|
|
class TeamMemberSerializer(serializers.ModelSerializer):
|
|
"""Serializer for team establishment BO section"""
|
|
|
|
class Meta:
|
|
model = account_models.User
|
|
fields = (
|
|
'id',
|
|
'username',
|
|
'email',
|
|
)
|
|
|
|
|
|
class BackEstablishmentAwardCreateSerializer(serializers.ModelSerializer):
|
|
"""Award, The Creator."""
|
|
award_type = serializers.PrimaryKeyRelatedField(required=True, queryset=main_models.AwardType.objects.all())
|
|
title = serializers.CharField(write_only=True)
|
|
|
|
class Meta:
|
|
model = models.Award
|
|
fields = (
|
|
'id',
|
|
'award_type',
|
|
'title',
|
|
'vintage_year',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
attrs['object_id'] = self.context.get('request').parser_context.get('kwargs')['establishment_id']
|
|
attrs['content_type'] = ContentType.objects.get_for_model(models.Establishment)
|
|
attrs['title'] = {self.context.get('request').locale: attrs['title']}
|
|
return attrs
|