From f82784cd19f8a1ccbbd618a0118cdc0017d1b002 Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Tue, 27 Aug 2019 12:33:16 +0300 Subject: [PATCH] update establishment-list endpoint --- apps/establishment/apps.py | 2 +- apps/establishment/migrations/0001_initial.py | 68 ++++++++++ apps/establishment/models.py | 117 +++++++++++++++++- apps/establishment/serializers.py | 46 +++++++ apps/establishment/urls/__init__.py | 0 apps/establishment/urls/common.py | 11 ++ apps/establishment/urls/web.py | 7 ++ apps/establishment/views.py | 34 +++++ project/urls/__init__.py | 2 - project/urls/web.py | 5 +- requirements/development.txt | 1 + 11 files changed, 282 insertions(+), 11 deletions(-) create mode 100644 apps/establishment/migrations/0001_initial.py create mode 100644 apps/establishment/serializers.py create mode 100644 apps/establishment/urls/__init__.py create mode 100644 apps/establishment/urls/common.py create mode 100644 apps/establishment/urls/web.py create mode 100644 apps/establishment/views.py diff --git a/apps/establishment/apps.py b/apps/establishment/apps.py index a78c0c7c..ee5512ad 100644 --- a/apps/establishment/apps.py +++ b/apps/establishment/apps.py @@ -2,7 +2,7 @@ from django.apps import AppConfig from django.utils.translation import ugettext_lazy as _ -class EstablishmentsConfig(AppConfig): +class EstablishmentConfig(AppConfig): name = 'establishment' verbose_name = _('Establishment') diff --git a/apps/establishment/migrations/0001_initial.py b/apps/establishment/migrations/0001_initial.py new file mode 100644 index 00000000..660aa80f --- /dev/null +++ b/apps/establishment/migrations/0001_initial.py @@ -0,0 +1,68 @@ +# Generated by Django 2.2.4 on 2019-08-27 09:29 + +import django.contrib.postgres.fields.jsonb +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import easy_thumbnails.fields +import utils.methods + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('location', '0007_auto_20190826_1342'), + ] + + operations = [ + migrations.CreateModel( + name='EstablishmentType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('name', models.CharField(max_length=255, unique=True, verbose_name='Name')), + ('use_subtypes', models.BooleanField(default=True, verbose_name='Use subtypes')), + ], + options={ + 'verbose_name': 'Establishment type', + 'verbose_name_plural': 'Establishment types', + }, + ), + migrations.CreateModel( + name='EstablishmentSubType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('name', models.CharField(max_length=255, unique=True, verbose_name='Name')), + ('establishment_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='establishment.EstablishmentType', verbose_name='Type')), + ], + options={ + 'verbose_name': 'Establishment subtype', + 'verbose_name_plural': 'Establishment subtypes', + }, + ), + migrations.CreateModel( + name='Establishment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='Date created')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('image', easy_thumbnails.fields.ThumbnailerImageField(blank=True, default=None, null=True, upload_to=utils.methods.image_path, verbose_name='Image')), + ('name', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=None, help_text='{"en":"some text"}', null=True, verbose_name='Name')), + ('description', django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=None, help_text='{"en":"some text"}', null=True, verbose_name='Description')), + ('public_mark', models.PositiveIntegerField(blank=True, default=None, null=True, verbose_name='Public mark')), + ('toque_number', models.PositiveIntegerField(blank=True, default=None, null=True, verbose_name='Toque number')), + ('address', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='location.Address', verbose_name='Address')), + ('establishment_subtypes', models.ManyToManyField(related_name='subtype_establishment', to='establishment.EstablishmentSubType', verbose_name='Subtype')), + ('establishment_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='establishment', to='establishment.EstablishmentType', verbose_name='Type')), + ], + options={ + 'verbose_name': 'Establishment', + 'verbose_name_plural': 'Establishments', + }, + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 4c84c7cc..989cf625 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -1,14 +1,119 @@ +"""Establishment models.""" from django.contrib.postgres.fields import JSONField +from django.core.exceptions import ValidationError from django.db import models from django.utils.translation import gettext_lazy as _ - -from utils.models import ProjectBaseMixin, ImageMixin +from location.models import Address +from utils.models import ProjectBaseMixin, ImageMixin, LocaleManagerMixin -class Establishment(ProjectBaseMixin): +# todo: establishment type&subtypes check +class EstablishmentType(ProjectBaseMixin): + """Establishment type model.""" + + name = models.CharField(_('Name'), max_length=255, unique=True) + use_subtypes = models.BooleanField(_('Use subtypes'), default=True) + + class Meta: + """Meta class.""" + + verbose_name = _('Establishment type') + verbose_name_plural = _('Establishment types') + + def __str__(self): + """__str__ method.""" + return self.name + + +class EstablishmentSubTypeManager(models.Manager): + """Extended manager for establishment subtype.""" + + def make(self, name, establishment_type): + obj = self.model(name=name, establishment_type=establishment_type) + obj.full_clean() + obj.save() + return obj + + +class EstablishmentSubType(ProjectBaseMixin): + """Establishment type model.""" + + name = models.CharField(_('Name'), max_length=255, unique=True) + establishment_type = models.ForeignKey(EstablishmentType, + on_delete=models.CASCADE, + verbose_name=_('Type')) + + objects = EstablishmentSubTypeManager() + + class Meta: + """Meta class.""" + + verbose_name = _('Establishment subtype') + verbose_name_plural = _('Establishment subtypes') + + def __str__(self): + """__str__ method.""" + return self.name + + def clean_fields(self, exclude=None): + if not self.establishment_type.use_subtypes: + raise ValidationError(_('Establishment type is not use subtypes.')) + + +class EstablishmentManager(LocaleManagerMixin): + """Extended manager for establishment model.""" + + +class Establishment(ProjectBaseMixin, ImageMixin): """Establishment model.""" - name = models.CharField(max_length=100) - description = JSONField() - country = models.ForeignKey('location.Country', on_delete=models.CASCADE) + name = JSONField(blank=True, null=True, default=None, + verbose_name=_('Name'), help_text='{"en":"some text"}') + description = JSONField(blank=True, null=True, default=None, + verbose_name=_('Description'), + help_text='{"en":"some text"}') + public_mark = models.PositiveIntegerField(blank=True, null=True, + default=None, + verbose_name=_('Public mark'),) + toque_number = models.PositiveIntegerField(blank=True, null=True, + default=None, + verbose_name=_('Toque number'),) + establishment_type = models.ForeignKey(EstablishmentType, + related_name='establishment', + on_delete=models.PROTECT, + verbose_name=_('Type')) + establishment_subtypes = models.ManyToManyField(EstablishmentSubType, + related_name='subtype_establishment', + verbose_name=_('Subtype')) + address = models.ForeignKey(Address, blank=True, null=True, default=None, + on_delete=models.PROTECT, + verbose_name=_('Address')) + objects = EstablishmentManager() + + class Meta: + """Meta class.""" + + verbose_name = _('Establishment') + verbose_name_plural = _('Establishments') + + # todo: recalculate toque_number + def recalculate_toque_number(self): + self.toque_number = 4 + + @property + def subtypes(self): + return EstablishmentSubType.objects.filter( + establishments=self, + establishment_type=self.establishment_type, + establishment_type__use_subtypes=True) + + def set_establishment_type(self, establishment_type): + self.establishment_type = establishment_type + self.establishment_subtypes.exclude( + establishement_type=establishment_type).delete() + + def add_establishment_subtype(self, establishment_subtype): + if establishment_subtype.establishment_type != self.establishment_type: + raise ValidationError('Establishment type of subtype does not match') + self.establishment_subtypes.add(establishment_subtype) diff --git a/apps/establishment/serializers.py b/apps/establishment/serializers.py new file mode 100644 index 00000000..81b438cb --- /dev/null +++ b/apps/establishment/serializers.py @@ -0,0 +1,46 @@ +"""Establishment serializers.""" +from rest_framework import serializers +from establishment import models + + +class EstablishmentTypeSerializer(serializers.ModelSerializer): + """Serializer for EstablishmentType model.""" + + class Meta: + """Meta class.""" + + model = models.EstablishmentType + fields = ('id', 'name', 'use_subtypes') + + +class EstablishmentSubTypeSerializer(serializers.ModelSerializer): + """Serializer for EstablishmentSubType models.""" + + class Meta: + """Meta class.""" + + model = models.EstablishmentSubType + fields = ('id', 'name') + + +class EstablishmentSerializer(serializers.ModelSerializer): + """Serializer for Establishment model.""" + + name_trans = serializers.CharField() + description_trans = serializers.CharField() + type = EstablishmentTypeSerializer(source='establishment_type') + subtypes = EstablishmentSubTypeSerializer(many=True) + + class Meta: + """Meta class.""" + + model = models.Establishment + fields = ( + 'id', + 'name_trans', + 'description_trans', + 'public_mark', + 'type', + 'subtypes', + 'address', + ) diff --git a/apps/establishment/urls/__init__.py b/apps/establishment/urls/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/establishment/urls/common.py b/apps/establishment/urls/common.py new file mode 100644 index 00000000..6542eec9 --- /dev/null +++ b/apps/establishment/urls/common.py @@ -0,0 +1,11 @@ +"""Establishment url patterns.""" +from django.urls import include, path +from establishment import views + + +app_name = 'establishment' + + +urlpatterns = [ + path('', views.EstablishmentListView.as_view(), name='establishment-list'), +] \ No newline at end of file diff --git a/apps/establishment/urls/web.py b/apps/establishment/urls/web.py new file mode 100644 index 00000000..b732d171 --- /dev/null +++ b/apps/establishment/urls/web.py @@ -0,0 +1,7 @@ +"""Establishment app web urlconf.""" +from establishment.urls.common import urlpatterns as common_urlpatterns + + +urlpatterns = [] + +urlpatterns.extend(common_urlpatterns) \ No newline at end of file diff --git a/apps/establishment/views.py b/apps/establishment/views.py new file mode 100644 index 00000000..094fca56 --- /dev/null +++ b/apps/establishment/views.py @@ -0,0 +1,34 @@ +"""Establishment app views.""" +from rest_framework import generics, permissions +from establishment import models, serializers +from utils.views import JWTGenericViewMixin + + +class EstablishmentListView(JWTGenericViewMixin, generics.ListAPIView): + """Resource for getting a list of establishments.""" + + pagination_class = None + permission_classes = (permissions.AllowAny,) + serializer_class = serializers.EstablishmentSerializer + + def get_queryset(self): + return models.Establishment.objects.annotate_localized_fields( + locale=self.request.locale) + + +class EstablishmentTypeListView(generics.ListAPIView): + """Resource for getting a list of establishment types.""" + + pagination_class = None + permission_classes = (permissions.AllowAny,) + queryset = models.EstablishmentType.objects.all() + serializer_class = serializers.EstablishmentTypeSerializer + + +class EstablishmentSubTypeListView(generics.ListAPIView): + """Resource for getting a list of establishment subtypes.""" + + pagination_class = None + permission_classes = (permissions.AllowAny,) + queryset = models.EstablishmentType.objects.all() + serializer_class = serializers.EstablishmentSubTypeSerializer diff --git a/project/urls/__init__.py b/project/urls/__init__.py index fd03905a..ef909dcf 100644 --- a/project/urls/__init__.py +++ b/project/urls/__init__.py @@ -54,8 +54,6 @@ urlpatterns_auth = [ ] api_urlpatterns = [ - path('establishments/', include(('establishment.urls', 'establishment'), - namespace='establishment')), path('location/', include(('location.urls', 'location'), namespace='location')), path('main/', include(('main.urls', 'main'), diff --git a/project/urls/web.py b/project/urls/web.py index 956d0c11..7f4a20c7 100644 --- a/project/urls/web.py +++ b/project/urls/web.py @@ -19,8 +19,9 @@ app_name = 'web' urlpatterns = [ path('account/', include('account.urls.web')), - path('news/', include('news.urls.web')), + path('advertisement/', include('advertisement.urls.web')), path('collection/', include('collection.urls.web')), + path('establishments/', include('establishment.urls.web')), + path('news/', include('news.urls.web')), path('partner/', include('partner.urls.web')), - path('advertisement/', include('advertisement.urls.web')) ] diff --git a/requirements/development.txt b/requirements/development.txt index 79801f49..21f7ead9 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -1,2 +1,3 @@ -r base.txt +ipdb ipython \ No newline at end of file