Added menu dishes

This commit is contained in:
dormantman 2020-01-29 16:11:53 +03:00
parent bcc5f2da51
commit a6db15ed50
5 changed files with 74 additions and 168 deletions

View File

@ -6,36 +6,32 @@ from typing import List
import elasticsearch_dsl import elasticsearch_dsl
from django.conf import settings from django.conf import settings
from django.shortcuts import get_object_or_404
from django.contrib.contenttypes import fields as generic from django.contrib.contenttypes import fields as generic
from django.contrib.gis.db.models.functions import Distance from django.contrib.gis.db.models.functions import Distance
from django.contrib.gis.geos import Point from django.contrib.gis.geos import Point
from django.contrib.gis.measure import Distance as DistanceMeasure from django.contrib.gis.measure import Distance as DistanceMeasure
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from django.contrib.postgres.search import TrigramDistance, TrigramSimilarity
from django.contrib.postgres.indexes import GinIndex from django.contrib.postgres.indexes import GinIndex
from django.contrib.postgres.search import TrigramSimilarity
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator, MaxValueValidator, FileExtensionValidator from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models from django.db import models
from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q, Prefetch, Sum from django.db.models import Case, ExpressionWrapper, F, Prefetch, Q, Subquery, When
from django.shortcuts import get_object_or_404
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
from timezone_field import TimeZoneField from timezone_field import TimeZoneField
from location.models import Address from location.models import Address
from timetable.models import Timetable
from location.models import WineOriginAddressMixin
from main.models import Award, Currency from main.models import Award, Currency
from review.models import Review from review.models import Review
from tag.models import Tag from tag.models import Tag
from timetable.models import Timetable
from utils.methods import transform_into_readable_str from utils.methods import transform_into_readable_str
from utils.models import ( from utils.models import (
ProjectBaseMixin, TJSONField, URLImageMixin, BaseAttributes, FavoritesMixin, FileMixin, GalleryMixin, HasTagsMixin, IntermediateGalleryModelMixin,
TranslatedFieldsMixin, BaseAttributes, GalleryMixin, ProjectBaseMixin, TJSONField, TranslatedFieldsMixin, TypeDefaultImageMixin, URLImageMixin,
IntermediateGalleryModelMixin, HasTagsMixin,
FavoritesMixin, TypeDefaultImageMixin, FileMixin,
ImageMixin,
) )
@ -564,8 +560,8 @@ class Establishment(GalleryMixin, ProjectBaseMixin, URLImageMixin,
verbose_name=_('Facebook URL')) verbose_name=_('Facebook URL'))
twitter = models.URLField(blank=True, null=True, default=None, max_length=255, twitter = models.URLField(blank=True, null=True, default=None, max_length=255,
verbose_name=_('Twitter URL')) verbose_name=_('Twitter URL'))
instagram =models.URLField(blank=True, null=True, default=None, max_length=255, instagram = models.URLField(blank=True, null=True, default=None, max_length=255,
verbose_name=_('Instagram URL')) verbose_name=_('Instagram URL'))
lafourchette = models.URLField(blank=True, null=True, default=None, max_length=255, lafourchette = models.URLField(blank=True, null=True, default=None, max_length=255,
verbose_name=_('Lafourchette URL')) verbose_name=_('Lafourchette URL'))
guestonline_id = models.PositiveIntegerField(blank=True, verbose_name=_('guestonline id'), guestonline_id = models.PositiveIntegerField(blank=True, verbose_name=_('guestonline id'),
@ -737,7 +733,8 @@ class Establishment(GalleryMixin, ProjectBaseMixin, URLImageMixin,
now_at_est_tz = datetime.now(tz=self.tz) now_at_est_tz = datetime.now(tz=self.tz)
current_week = now_at_est_tz.weekday() current_week = now_at_est_tz.weekday()
schedule_for_today = self.schedule.filter(weekday=current_week).first() schedule_for_today = self.schedule.filter(weekday=current_week).first()
if schedule_for_today is None or schedule_for_today.opening_time is None or schedule_for_today.ending_time is None: if schedule_for_today is None or schedule_for_today.opening_time is None or schedule_for_today.ending_time is\
None:
return False return False
time_at_est_tz = now_at_est_tz.time() time_at_est_tz = now_at_est_tz.time()
return schedule_for_today.ending_time > time_at_est_tz > schedule_for_today.opening_time return schedule_for_today.ending_time > time_at_est_tz > schedule_for_today.opening_time
@ -749,8 +746,10 @@ class Establishment(GalleryMixin, ProjectBaseMixin, URLImageMixin,
@property @property
def tags_indexing(self): def tags_indexing(self):
return [{'id': tag.metadata.id, return [{
'label': tag.metadata.label} for tag in self.tags.all()] 'id': tag.metadata.id,
'label': tag.metadata.label
} for tag in self.tags.all()]
@property @property
def last_published_review(self): def last_published_review(self):
@ -1244,6 +1243,24 @@ class Plate(TranslatedFieldsMixin, models.Model):
verbose_name_plural = _('plates') verbose_name_plural = _('plates')
class MenuDish(BaseAttributes):
"""Dish model."""
STR_FIELD_NAME = 'category'
name = models.CharField(_('name'), max_length=255, default='')
category = TJSONField(
blank=True, null=True, default=None, verbose_name=_('category'),
help_text='{"en-GB":"some text"}')
price = models.IntegerField(blank=True, null=True, default=None, verbose_name=_('price'))
signature = models.BooleanField(_('signature'), default=False)
class Meta:
verbose_name = _('dish')
verbose_name_plural = _('dishes')
ordering = ('-created',)
class MenuQuerySet(models.QuerySet): class MenuQuerySet(models.QuerySet):
def with_schedule_plates_establishment(self): def with_schedule_plates_establishment(self):
return self.select_related( return self.select_related(
@ -1270,15 +1287,10 @@ class MenuQuerySet(models.QuerySet):
return self.filter(category__icontains=value) return self.filter(category__icontains=value)
class Menu(GalleryMixin, TranslatedFieldsMixin, BaseAttributes): class Menu(TranslatedFieldsMixin, BaseAttributes):
"""Menu model.""" """Menu model."""
STR_FIELD_NAME = 'category'
name = models.CharField(_('name'), max_length=255, default='') name = models.CharField(_('name'), max_length=255, default='')
category = TJSONField(
blank=True, null=True, default=None, verbose_name=_('category'),
help_text='{"en-GB":"some text"}')
establishment = models.ForeignKey( establishment = models.ForeignKey(
'establishment.Establishment', verbose_name=_('establishment'), 'establishment.Establishment', verbose_name=_('establishment'),
on_delete=models.CASCADE) on_delete=models.CASCADE)
@ -1294,6 +1306,14 @@ class Menu(GalleryMixin, TranslatedFieldsMixin, BaseAttributes):
blank=True, blank=True,
verbose_name=_('Menu files'), verbose_name=_('Menu files'),
) )
dishes = models.ManyToManyField(
to='MenuDish',
blank=True,
verbose_name=_('Menu dishes')
)
category = TJSONField(
blank=True, null=True, default=None, verbose_name=_('category'),
help_text='{"en-GB":"some text"}')
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None) old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)

View File

@ -1,12 +1,14 @@
from functools import lru_cache from functools import lru_cache
from django.db.models import F from django.db.models import F
from django.shortcuts import get_object_or_404
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from account.serializers.common import UserShortSerializer from account.serializers.common import UserShortSerializer
from establishment import models, serializers as model_serializers from establishment import models, serializers as model_serializers
from establishment.models import ContactPhone, EstablishmentEmployee, ContactEmail from establishment.models import ContactPhone, EstablishmentEmployee, ContactEmail
from establishment.serializers import MenuDishSerializer
from gallery.models import Image from gallery.models import Image
from location.models import Address from location.models import Address
from location.serializers import AddressDetailSerializer, TranslatedField from location.serializers import AddressDetailSerializer, TranslatedField
@ -580,109 +582,36 @@ class EstablishmentEmployeePositionsSerializer(serializers.ModelSerializer):
] ]
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): class MenuDishesSerializer(ProjectModelSerializer):
"""for dessert, main_course and starter category""" """for dessert, main_course and starter category"""
plates = _PlateSerializer(read_only=True, many=True, source='plate_set', allow_null=True) establishment_id = serializers.PrimaryKeyRelatedField(read_only=True)
category_translated = serializers.CharField(read_only=True) establishment_slug = serializers.CharField(read_only=True, source='establishment.slug')
last_update = serializers.DateTimeField(source='created') dishes = MenuDishSerializer(many=True, read_only=True)
gallery = ImageBaseSerializer(read_only=True, source='crop_gallery', many=True)
class Meta: class Meta:
model = models.Menu model = models.Menu
fields = [ fields = [
'id', 'id',
'category', 'establishment_id',
'category_translated', 'establishment_slug',
'establishment', 'dishes',
'is_drinks_included',
'schedule',
'plates',
'last_update',
'gallery',
] ]
class MenuDishesRUDSerializers(ProjectModelSerializer): class MenuDishesRUDSerializers(ProjectModelSerializer):
"""for dessert, main_course and starter category""" """for dessert, main_course and starter category"""
plates = _PlateSerializer(read_only=True, many=True, source='plate_set', allow_null=True) establishment_id = serializers.PrimaryKeyRelatedField(queryset=models.Establishment.objects.all())
gallery = ImageBaseSerializer(read_only=True, source='crop_gallery', many=True) establishment_slug = serializers.CharField(read_only=True, source='establishment.slug')
dishes = MenuDishSerializer(many=True, read_only=True)
class Meta: class Meta:
model = models.Menu model = models.Menu
fields = [ fields = [
'id', 'id',
'category', 'establishment_id',
'plates', 'establishment_slug',
'establishment', 'dishes',
'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

View File

@ -72,6 +72,19 @@ class PlateSerializer(ProjectModelSerializer):
] ]
class MenuDishSerializer(ProjectModelSerializer):
class Meta:
model = models.MenuDish
fields = [
'id',
'name',
'category',
'category_translated',
'price',
'signature'
]
class MenuFilesSerializers(ProjectModelSerializer): class MenuFilesSerializers(ProjectModelSerializer):
menu_id = serializers.IntegerField(write_only=True) menu_id = serializers.IntegerField(write_only=True)
@ -113,7 +126,6 @@ class MenuSerializers(ProjectModelSerializer):
'drinks_included', 'drinks_included',
'schedules', 'schedules',
'uploads', 'uploads',
'category',
] ]
def create(self, validated_data): def create(self, validated_data):
@ -142,7 +154,6 @@ class MenuRUDSerializers(ProjectModelSerializer):
'drinks_included', 'drinks_included',
'schedules', 'schedules',
'uploads', 'uploads',
'category',
] ]

View File

@ -30,13 +30,11 @@ urlpatterns = [
name='note-rud'), name='note-rud'),
path('slug/<slug:slug>/admin/', views.EstablishmentAdminView.as_view(), path('slug/<slug:slug>/admin/', views.EstablishmentAdminView.as_view(),
name='establishment-admin-list'), name='establishment-admin-list'),
path('menus/dishes/', views.MenuDishesListCreateView.as_view(), name='menu-dishes-list'), path('menus/dishes/', views.MenuDishesListView.as_view(), name='menu-dishes-list'),
path('menus/dishes/<int:pk>/', views.MenuDishesRUDView.as_view(), name='menu-dishes-rud'), path('menus/dishes/<int:pk>/', views.MenuDishesRUDView.as_view(), name='menu-dishes-rud'),
# path('menus/dishes/<int:pk>/gallery/', views.MenuGalleryListView.as_view(), name='menu-dishes-gallery-list'),
# path('menus/dishes/<int:pk>/gallery/<int:image_id>/', views.MenuGalleryCreateDestroyView.as_view(),
# name='menu-dishes-gallery-create-destroy'),
path('menus/', views.MenuListCreateView.as_view(), name='menu-list'), path('menus/', views.MenuListCreateView.as_view(), name='menu-list'),
path('menus/<int:pk>/', views.MenuRUDView.as_view(), name='menu-rud'), path('menus/<int:pk>/', views.MenuRUDView.as_view(), name='menu-rud'),
path('menus/slug/<slug:slug>/', views.MenuRUDView.as_view(), name='menu-rud'),
path('menus/uploads/', views.MenuFilesListCreateView.as_view(), name='menu-files-list'), path('menus/uploads/', views.MenuFilesListCreateView.as_view(), name='menu-files-list'),
path('menus/uploads/<int:pk>/', views.MenuFilesRUDView.as_view(), name='menu-files-rud'), path('menus/uploads/<int:pk>/', views.MenuFilesRUDView.as_view(), name='menu-files-rud'),
path('plates/', views.PlateListCreateView.as_view(), name='plates'), path('plates/', views.PlateListCreateView.as_view(), name='plates'),

View File

@ -466,10 +466,10 @@ class EstablishmentAdminView(generics.ListAPIView):
return User.objects.establishment_admin(establishment).distinct() return User.objects.establishment_admin(establishment).distinct()
class MenuDishesListCreateView(generics.ListCreateAPIView): class MenuDishesListView(generics.ListAPIView):
"""Menu (dessert, main_course, starter) list create view.""" """Menu (dessert, main_course, starter) list create view."""
serializer_class = serializers.MenuDishesSerializer serializer_class = serializers.MenuDishesSerializer
queryset = models.Menu.objects.with_schedule_plates_establishment().dishes().distinct() queryset = models.Menu.objects.all()
permission_classes = [IsWineryReviewer | IsEstablishmentManager] permission_classes = [IsWineryReviewer | IsEstablishmentManager]
filter_class = filters.MenuDishesBackFilter filter_class = filters.MenuDishesBackFilter
@ -477,57 +477,5 @@ class MenuDishesListCreateView(generics.ListCreateAPIView):
class MenuDishesRUDView(generics.RetrieveUpdateDestroyAPIView): class MenuDishesRUDView(generics.RetrieveUpdateDestroyAPIView):
"""Menu (dessert, main_course, starter) RUD view.""" """Menu (dessert, main_course, starter) RUD view."""
serializer_class = serializers.MenuDishesRUDSerializers serializer_class = serializers.MenuDishesRUDSerializers
queryset = models.Menu.objects.dishes().distinct() queryset = models.Menu.objects.all()
permission_classes = [IsWineryReviewer | IsEstablishmentManager] permission_classes = [IsWineryReviewer | IsEstablishmentManager]
# class MenuGalleryListView(generics.ListAPIView):
# """Resource for returning gallery for menu for back-office users."""
# serializer_class = serializers.ImageBaseSerializer
# permission_classes = [IsWineryReviewer | IsEstablishmentManager]
# 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 = [IsWineryReviewer | IsEstablishmentManager]
#
# 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