diff --git a/apps/establishment/admin.py b/apps/establishment/admin.py index 19b34cdd..d43171bf 100644 --- a/apps/establishment/admin.py +++ b/apps/establishment/admin.py @@ -60,11 +60,6 @@ class EstablishmentAdmin(admin.ModelAdmin): ReviewInline, CommentInline] -@admin.register(models.EstablishmentSchedule) -class EstablishmentSchedule(admin.ModelAdmin): - """Establishment schedule""" - - @admin.register(models.Position) class PositionAdmin(admin.ModelAdmin): """Position admin.""" diff --git a/apps/establishment/migrations/0021_delete_establishmentschedule.py b/apps/establishment/migrations/0021_delete_establishmentschedule.py new file mode 100644 index 00000000..c475bbcb --- /dev/null +++ b/apps/establishment/migrations/0021_delete_establishmentschedule.py @@ -0,0 +1,16 @@ +# Generated by Django 2.2.4 on 2019-09-18 12:07 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0020_merge_20190917_1415'), + ] + + operations = [ + migrations.DeleteModel( + name='EstablishmentSchedule', + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 00115303..6a2c0160 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -262,6 +262,9 @@ class Establishment(ProjectBaseMixin, ImageMixin, TranslatedFieldsMixin): booking = models.URLField(blank=True, null=True, default=None, verbose_name=_('Booking URL')) is_publish = models.BooleanField(default=False, verbose_name=_('Publish status')) + schedule = models.ManyToManyField(to='timetable.Timetable', + verbose_name=_('Establishment schedule'), + related_name='schedule') awards = generic.GenericRelation(to='main.Award') tags = generic.GenericRelation(to='main.MetaDataContent') reviews = generic.GenericRelation(to='review.Review') @@ -392,23 +395,6 @@ class EstablishmentScheduleQuerySet(models.QuerySet): """QuerySet for model EstablishmentSchedule""" -class EstablishmentSchedule(BaseAttributes): - """Establishment schedule model.""" - establishment = models.OneToOneField(Establishment, - related_name='schedule', - on_delete=models.CASCADE, - verbose_name=_('Establishment')) - schedule = models.ManyToManyField(to='timetable.Timetable', - verbose_name=_('Establishment schedule')) - - objects = EstablishmentScheduleQuerySet.as_manager() - - class Meta: - """Meta class""" - verbose_name = _('Establishment schedule') - verbose_name_plural = _('Establishment schedules') - - class ContactPhone(models.Model): """Contact phone model.""" establishment = models.ForeignKey( diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py index 1c7d9d27..6720677d 100644 --- a/apps/establishment/serializers/back.py +++ b/apps/establishment/serializers/back.py @@ -1,9 +1,12 @@ +import json from rest_framework import serializers from establishment import models +from timetable.models import Timetable from establishment.serializers import ( EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer, - ContactPhonesSerializer, SocialNetworkRelatedSerializers) + ContactPhonesSerializer, SocialNetworkRelatedSerializers, EstablishmentDetailSerializer +) from main.models import Currency @@ -82,4 +85,4 @@ class ContactEmailBackSerializers(PlateSerializer): 'id', 'establishment', 'email' - ] \ No newline at end of file + ] diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py index 740a5f93..18d07ce5 100644 --- a/apps/establishment/serializers/common.py +++ b/apps/establishment/serializers/common.py @@ -9,7 +9,7 @@ from location.serializers import AddressSerializer from main.models import MetaDataContent from main.serializers import MetaDataContentSerializer, AwardSerializer, CurrencySerializer from review import models as review_models -from timetable.models import Timetable +from timetable.serialziers import ScheduleRUDSerializer from utils import exceptions as utils_exceptions @@ -111,22 +111,6 @@ class EstablishmentSubTypeSerializer(serializers.ModelSerializer): fields = ('id', 'name_translated') -class EstablishmentScheduleSerializer(serializers.ModelSerializer): - """Serializer for Establishment model.""" - weekday = serializers.CharField(source='get_weekday_display') - - class Meta: - """Meta class.""" - model = Timetable - fields = ( - 'weekday', - 'lunch_start', - 'lunch_end', - 'dinner_start', - 'dinner_end', - ) - - class ReviewSerializer(serializers.ModelSerializer): """Serializer for model Review.""" text_translated = serializers.CharField(read_only=True) @@ -203,9 +187,7 @@ class EstablishmentDetailSerializer(EstablishmentListSerializer): """Serializer for Establishment model.""" description_translated = serializers.CharField(allow_null=True) awards = AwardSerializer(many=True) - schedule = EstablishmentScheduleSerializer(source='schedule.schedule', - many=True, - allow_null=True) + schedule = ScheduleRUDSerializer(many=True, allow_null=True) phones = ContactPhonesSerializer(read_only=True, many=True, ) emails = ContactEmailsSerializer(read_only=True, many=True, ) review = serializers.SerializerMethodField() diff --git a/apps/establishment/urls/back.py b/apps/establishment/urls/back.py index bce07ee5..110f9d63 100644 --- a/apps/establishment/urls/back.py +++ b/apps/establishment/urls/back.py @@ -10,6 +10,10 @@ app_name = 'establishment' urlpatterns = [ path('', views.EstablishmentListCreateView.as_view(), name='list'), path('/', views.EstablishmentRetrieveView.as_view(), name='detail'), + path('/schedule//', views.EstablishmentScheduleRUDView.as_view(), + name='schedule-rud'), + path('/schedule/', views.EstablishmentScheduleCreateView.as_view(), + name='schedule-create'), path('menus/', views.MenuListCreateView.as_view(), name='menu-list'), path('menus//', views.MenuRUDView.as_view(), name='menu-rud'), path('plates/', views.PlateListCreateView.as_view(), name='plates'), diff --git a/apps/establishment/views/back.py b/apps/establishment/views/back.py index 14488993..8e38325b 100644 --- a/apps/establishment/views/back.py +++ b/apps/establishment/views/back.py @@ -2,7 +2,8 @@ from rest_framework import generics -from establishment import models, serializers +from establishment import models +from establishment import serializers from establishment.views.common import EstablishmentMixin diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py index cc0d1c56..4ca5c4fe 100644 --- a/apps/establishment/views/web.py +++ b/apps/establishment/views/web.py @@ -7,8 +7,9 @@ from comment import models as comment_models from establishment import filters from establishment import models, serializers from main.models import MetaDataContent -from utils.views import JWTGenericViewMixin from establishment.views import EstablishmentMixin +from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer +from timetable.models import Timetable class EstablishmentListView(EstablishmentMixin, generics.ListAPIView): @@ -34,12 +35,12 @@ class EstablishmentSimilarListView(EstablishmentListView): .order_by('-total_mark')[:13] -class EstablishmentRetrieveView(EstablishmentMixin, JWTGenericViewMixin, generics.RetrieveAPIView): +class EstablishmentRetrieveView(EstablishmentMixin, generics.RetrieveAPIView): """Resource for getting a establishment.""" serializer_class = serializers.EstablishmentDetailSerializer -class EstablishmentTypeListView(JWTGenericViewMixin, generics.ListAPIView): +class EstablishmentTypeListView(generics.ListAPIView): """Resource for getting a list of establishment types.""" permission_classes = (permissions.AllowAny,) @@ -122,7 +123,7 @@ class EstablishmentFavoritesCreateDestroyView(generics.CreateAPIView, generics.D return obj -class EstablishmentNearestRetrieveView(EstablishmentMixin, JWTGenericViewMixin, generics.ListAPIView): +class EstablishmentNearestRetrieveView(EstablishmentMixin, generics.ListAPIView): """Resource for getting list of nearest establishments.""" serializer_class = serializers.EstablishmentListSerializer filter_class = filters.EstablishmentFilter @@ -151,3 +152,40 @@ class EstablishmentTagListView(generics.ListAPIView): """Override get_queryset method""" return MetaDataContent.objects.by_content_type(app_label='establishment', model='establishment') + + +class EstablishmentScheduleRUDView(generics.RetrieveUpdateDestroyAPIView): + """Establishment schedule RUD view""" + serializer_class = ScheduleRUDSerializer + + def get_object(self): + """ + Returns the object the view is displaying. + """ + lookup_url_kwargs = ('pk', 'schedule_id') + + assert lookup_url_kwargs not in self.kwargs.keys(), ( + '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_kwargs) + ) + + establishment_pk = self.kwargs['pk'] + schedule_id = self.kwargs['schedule_id'] + + establishment = get_object_or_404(klass=models.Establishment.objects.all(), + pk=establishment_pk) + 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): + """Establishment schedule Create view""" + serializer_class = ScheduleCreateSerializer diff --git a/apps/main/models.py b/apps/main/models.py index 0078a5d5..bd7722fd 100644 --- a/apps/main/models.py +++ b/apps/main/models.py @@ -331,11 +331,10 @@ class Carousel(models.Model): @property def image(self): - # Check if Generic obj has an image - if not hasattr(self.content_object.image, 'url'): - # Check if Generic obj has a FK to gallery + if hasattr(self.content_object.image, 'url'): + return self.content_object.image + if hasattr(self.content_object.image.image, 'url'): return self.content_object.image.image - return self.content_object.image @property def model_name(self): diff --git a/apps/timetable/serialziers.py b/apps/timetable/serialziers.py index bf239858..899833fa 100644 --- a/apps/timetable/serialziers.py +++ b/apps/timetable/serialziers.py @@ -1,16 +1,58 @@ """Serializer for app timetable""" from rest_framework import serializers -from timetable import models +from timetable.models import Timetable +from establishment.models import Establishment -class TimetableSerializer(serializers.ModelSerializer): - """Serializer for model Timetable""" +class ScheduleRUDSerializer(serializers.ModelSerializer): + """Serializer for Establishment model.""" + weekday_display = serializers.CharField(source='get_weekday_display', + read_only=True) class Meta: """Meta class.""" - model = models.Timetable - fields = ( + model = Timetable + fields = [ + 'id', + 'weekday_display', + 'lunch_start', + 'lunch_end', + 'dinner_start', + 'dinner_end', + ] + + +class ScheduleCreateSerializer(ScheduleRUDSerializer): + """Serializer for Establishment model.""" + weekday = serializers.IntegerField(write_only=True) + + class Meta: + """Meta class.""" + model = Timetable + fields = ScheduleRUDSerializer.Meta.fields + [ 'weekday', - 'start', - 'end', - ) + ] + + def validate(self, attrs): + """Override validate method""" + return attrs + + def create(self, validated_data): + """Override create method""" + instance = super().create(validated_data) + weekday = validated_data.get('weekday') + establishment_pk = self.context.get('request')\ + .parser_context.get('view')\ + .kwargs.get('pk') + + establishment_qs = Establishment.objects.filter(pk=establishment_pk) + if not establishment_qs.exists(): + # todo: replace on appropriate exception + raise serializers.ValidationError() + + establishment = establishment_qs.first() + schedule_qs = establishment.schedule.filter(weekday=weekday) + if schedule_qs.exists(): + schedule_qs.delete() + establishment.schedule.add(instance) + return instance