added model Product and bo endpoints

This commit is contained in:
Anatoly 2019-11-18 17:24:15 +03:00
parent 2a680311ae
commit 0d9d45bcc5
12 changed files with 273 additions and 43 deletions

View File

@ -60,6 +60,12 @@ class Advertisement(ProjectBaseMixin):
def __str__(self): def __str__(self):
return str(self.url) return str(self.url)
def delete(self, using=None, keep_parents=False):
"""Overridden delete method."""
# Delete all related pages.
self.pages.all().delete()
return super().delete(using, keep_parents)
@property @property
def mobile_page(self): def mobile_page(self):
"""Return mobile page""" """Return mobile page"""

View File

@ -9,9 +9,9 @@ app_name = 'advertisements'
urlpatterns = [ urlpatterns = [
path('', views.AdvertisementListCreateView.as_view(), name='list-create'), path('', views.AdvertisementListCreateView.as_view(), name='list-create'),
path('<int:pk>/', views.AdvertisementRUDView.as_view(), name='rud'), path('<int:pk>/', views.AdvertisementRUDView.as_view(), name='rud'),
path('<int:pk>/page/', views.AdvertisementPageListCreateView.as_view(), path('<int:pk>/pages/', views.AdvertisementPageListCreateView.as_view(),
name='page-list-create'), name='page-list-create'),
path('<int:ad_pk>/page/<int:page_pk>/', views.AdvertisementPageRUDView.as_view(), path('<int:ad_pk>/pages/<int:page_pk>/', views.AdvertisementPageRUDView.as_view(),
name='page-rud') name='page-rud')
] ]

View File

@ -33,14 +33,6 @@ class AdvertisementRUDView(AdvertisementBackOfficeViewMixin,
serializer_class = AdvertisementBaseSerializer serializer_class = AdvertisementBaseSerializer
def delete(self, request, *args, **kwargs):
instance = self.get_object()
# Delete all object that linked to this advertisement
instance.pages.all().delete()
# Delete an instance
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
class AdvertisementPageListCreateView(AdvertisementBackOfficeViewMixin, class AdvertisementPageListCreateView(AdvertisementBackOfficeViewMixin,
generics.ListCreateAPIView): generics.ListCreateAPIView):
@ -66,7 +58,6 @@ class AdvertisementPageListCreateView(AdvertisementBackOfficeViewMixin,
class AdvertisementPageRUDView(AdvertisementBackOfficeViewMixin, class AdvertisementPageRUDView(AdvertisementBackOfficeViewMixin,
generics.CreateAPIView,
generics.RetrieveUpdateDestroyAPIView): generics.RetrieveUpdateDestroyAPIView):
"""Create|Retrieve|Update|Destroy advertisement page view.""" """Create|Retrieve|Update|Destroy advertisement page view."""

View File

@ -59,13 +59,18 @@ class ProductInline(admin.TabularInline):
extra = 0 extra = 0
class CompanyInline(admin.TabularInline):
model = models.Company
extra = 0
@admin.register(models.Establishment) @admin.register(models.Establishment)
class EstablishmentAdmin(BaseModelAdminMixin, admin.ModelAdmin): class EstablishmentAdmin(BaseModelAdminMixin, admin.ModelAdmin):
"""Establishment admin.""" """Establishment admin."""
list_display = ['id', '__str__', 'image_tag', ] list_display = ['id', '__str__', 'image_tag', ]
search_fields = ['id', 'name', 'index_name', 'slug'] search_fields = ['id', 'name', 'index_name', 'slug']
list_filter = ['public_mark', 'toque_number'] list_filter = ['public_mark', 'toque_number']
inlines = [GalleryImageInline, ] inlines = [GalleryImageInline, CompanyInline]
# inlines = [ # inlines = [
# AwardInline, ContactPhoneInline, ContactEmailInline, # AwardInline, ContactPhoneInline, ContactEmailInline,
@ -114,3 +119,9 @@ class SocialChoiceAdmin(BaseModelAdminMixin, admin.ModelAdmin):
class SocialNetworkAdmin(BaseModelAdminMixin, admin.ModelAdmin): class SocialNetworkAdmin(BaseModelAdminMixin, admin.ModelAdmin):
"""Admin conf for SocialNetwork model.""" """Admin conf for SocialNetwork model."""
raw_id_fields = ('establishment',) raw_id_fields = ('establishment',)
@admin.register(models.Company)
class CompanyAdmin(BaseModelAdminMixin, admin.ModelAdmin):
"""Admin conf for Company model."""
raw_id_fields = ['establishment', 'address', ]

View File

@ -0,0 +1,40 @@
# Generated by Django 2.2.7 on 2019-11-18 14:19
import django.contrib.postgres.fields
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
import phonenumber_field.modelfields
class Migration(migrations.Migration):
dependencies = [
('location', '0027_auto_20191118_1313'),
('establishment', '0062_auto_20191117_1117'),
]
operations = [
migrations.CreateModel(
name='Company',
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, verbose_name='name')),
('phones', django.contrib.postgres.fields.ArrayField(base_field=phonenumber_field.modelfields.PhoneNumberField(max_length=128), blank=True, default=None, null=True, size=None, verbose_name='contact phones')),
('faxes', django.contrib.postgres.fields.ArrayField(base_field=phonenumber_field.modelfields.PhoneNumberField(max_length=128), blank=True, default=None, null=True, size=None, verbose_name='fax numbers')),
('legal_entity', models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='legal entity')),
('registry_number', models.CharField(blank=True, default=None, max_length=255, null=True, verbose_name='registry number')),
('vat_number', models.CharField(blank=True, default=None, max_length=30, null=True, verbose_name='VAT identification number')),
('sic_code', models.IntegerField(blank=True, default=True, null=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(9999)], verbose_name='sic code')),
('address', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='companies', to='location.Address', verbose_name='address')),
('establishment', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='companies', to='establishment.Establishment', verbose_name='establishment')),
],
options={
'verbose_name': 'company',
'verbose_name_plural': 'companies',
},
),
]

View File

@ -16,6 +16,8 @@ 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 django.contrib.postgres.fields import ArrayField
from django.core.validators import MinValueValidator, MaxValueValidator
from collection.models import Collection from collection.models import Collection
from location.models import Address from location.models import Address
@ -408,6 +410,12 @@ class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin, Translat
def __str__(self): def __str__(self):
return f'id:{self.id}-{self.name}' return f'id:{self.id}-{self.name}'
def delete(self, using=None, keep_parents=False):
"""Overridden delete method"""
# Delete all related companies
self.companies.all().delete()
return super().delete(using, keep_parents)
@property @property
def visible_tags(self): def visible_tags(self):
return self.tags.exclude(category__value_type=TagCategory.BOOLEAN)\ return self.tags.exclude(category__value_type=TagCategory.BOOLEAN)\
@ -872,3 +880,46 @@ class RatingStrategy(ProjectBaseMixin):
return f'{self.country.code if self.country else "Other country"}. ' \ return f'{self.country.code if self.country else "Other country"}. ' \
f'"{self.toque_number}": {self.public_mark_min_value}-' \ f'"{self.toque_number}": {self.public_mark_min_value}-' \
f'{self.public_mark_max_value}' f'{self.public_mark_max_value}'
class CompanyQuerySet(models.QuerySet):
"""QuerySet for model Company."""
class Company(ProjectBaseMixin):
"""Establishment company model."""
establishment = models.ForeignKey(Establishment, on_delete=models.PROTECT,
related_name='companies',
verbose_name=_('establishment'))
name = models.CharField(max_length=255, verbose_name=_('name'))
phones = ArrayField(PhoneNumberField(max_length=128),
blank=True, null=True, default=None,
verbose_name=_('contact phones'))
faxes = ArrayField(PhoneNumberField(max_length=128),
blank=True, null=True, default=None,
verbose_name=_('fax numbers'))
legal_entity = models.CharField(max_length=255,
blank=True, null=True, default=None,
verbose_name=_('legal entity'))
registry_number = models.CharField(max_length=255,
blank=True, null=True, default=None,
verbose_name=_('registry number'))
vat_number = models.CharField(max_length=30,
blank=True, null=True, default=None,
verbose_name=_('VAT identification number'))
sic_code = models.IntegerField(validators=[MinValueValidator(1),
MaxValueValidator(9999)],
blank=True, null=True, default=True,
verbose_name=_('sic code'))
address = models.ForeignKey(Address, on_delete=models.PROTECT,
blank=True, null=True, default=None,
related_name='companies',
verbose_name=_('address'))
objects = CompanyQuerySet.as_manager()
class Meta:
"""Meta class."""
verbose_name = _('company')
verbose_name_plural = _('companies')

View File

@ -1,10 +1,7 @@
from rest_framework import serializers from rest_framework import serializers
from establishment import models from establishment import models
from establishment.serializers import ( from establishment import serializers as model_serializers
EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer,
ContactPhonesSerializer, SocialNetworkRelatedSerializers,
EstablishmentTypeBaseSerializer)
from location.serializers import AddressDetailSerializer from location.serializers import AddressDetailSerializer
from main.models import Currency from main.models import Currency
from utils.decorators import with_base_attributes from utils.decorators import with_base_attributes
@ -13,17 +10,22 @@ from gallery.models import Image
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
class EstablishmentListCreateSerializer(EstablishmentBaseSerializer): class EstablishmentListCreateSerializer(model_serializers.EstablishmentBaseSerializer):
"""Establishment create serializer""" """Establishment create serializer"""
type_id = serializers.PrimaryKeyRelatedField( type_id = serializers.PrimaryKeyRelatedField(
source='establishment_type', source='establishment_type',
queryset=models.EstablishmentType.objects.all(), write_only=True queryset=models.EstablishmentType.objects.all(),
write_only=True
) )
phones = ContactPhonesSerializer(read_only=True, many=True, ) phones = model_serializers.ContactPhonesSerializer(read_only=True,
emails = ContactEmailsSerializer(read_only=True, many=True, ) many=True, )
socials = SocialNetworkRelatedSerializers(read_only=True, many=True, ) emails = model_serializers.ContactEmailsSerializer(read_only=True,
type = EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True) many=True, )
socials = model_serializers.SocialNetworkRelatedSerializers(read_only=True,
many=True, )
type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type',
read_only=True)
tz = TimeZoneChoiceField() tz = TimeZoneChoiceField()
class Meta: class Meta:
@ -52,7 +54,7 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer):
] ]
class EstablishmentRUDSerializer(EstablishmentBaseSerializer): class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
"""Establishment create serializer""" """Establishment create serializer"""
type_id = serializers.PrimaryKeyRelatedField( type_id = serializers.PrimaryKeyRelatedField(
@ -60,10 +62,13 @@ class EstablishmentRUDSerializer(EstablishmentBaseSerializer):
queryset=models.EstablishmentType.objects.all(), write_only=True queryset=models.EstablishmentType.objects.all(), write_only=True
) )
address = AddressDetailSerializer() address = AddressDetailSerializer()
phones = ContactPhonesSerializer(read_only=False, many=True, ) phones = model_serializers.ContactPhonesSerializer(read_only=False,
emails = ContactEmailsSerializer(read_only=False, many=True, ) many=True, )
socials = SocialNetworkRelatedSerializers(read_only=False, many=True, ) emails = model_serializers.ContactEmailsSerializer(read_only=False,
type = EstablishmentTypeBaseSerializer(source='establishment_type') many=True, )
socials = model_serializers.SocialNetworkRelatedSerializers(read_only=False,
many=True, )
type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type')
class Meta: class Meta:
model = models.Establishment model = models.Establishment
@ -107,7 +112,7 @@ class SocialNetworkSerializers(serializers.ModelSerializer):
] ]
class PlatesSerializers(PlateSerializer): class PlatesSerializers(model_serializers.PlateSerializer):
"""Plates serializers.""" """Plates serializers."""
currency_id = serializers.PrimaryKeyRelatedField( currency_id = serializers.PrimaryKeyRelatedField(
@ -119,14 +124,14 @@ class PlatesSerializers(PlateSerializer):
"""Meta class.""" """Meta class."""
model = models.Plate model = models.Plate
fields = PlateSerializer.Meta.fields + [ fields = model_serializers.PlateSerializer.Meta.fields + [
'name', 'name',
'currency_id', 'currency_id',
'menu' 'menu'
] ]
class ContactPhoneBackSerializers(PlateSerializer): class ContactPhoneBackSerializers(model_serializers.PlateSerializer):
"""ContactPhone serializers.""" """ContactPhone serializers."""
class Meta: class Meta:
@ -138,7 +143,7 @@ class ContactPhoneBackSerializers(PlateSerializer):
] ]
class ContactEmailBackSerializers(PlateSerializer): class ContactEmailBackSerializers(model_serializers.PlateSerializer):
"""ContactEmail serializers.""" """ContactEmail serializers."""
class Meta: class Meta:
@ -204,3 +209,18 @@ class EstablishmentBackOfficeGallerySerializer(serializers.ModelSerializer):
attrs['image'] = image attrs['image'] = image
return attrs 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)

View File

@ -2,6 +2,7 @@
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from phonenumber_field.modelfields import PhoneNumberField
from comment import models as comment_models from comment import models as comment_models
from comment.serializers import common as comment_serializers from comment.serializers import common as comment_serializers
from establishment import models from establishment import models
@ -418,3 +419,41 @@ class EstablishmentFavoritesCreateSerializer(FavoritesCreateSerializer):
'content_object': validated_data.pop('establishment') 'content_object': validated_data.pop('establishment')
}) })
return super().create(validated_data) return super().create(validated_data)
class CompanyBaseSerializer(serializers.ModelSerializer):
"""Company base serializer"""
phone_list = serializers.SerializerMethodField(source='phones', read_only=True)
fax_list = serializers.SerializerMethodField(source='faxes', read_only=True)
address_detail = AddressDetailSerializer(source='address', read_only=True)
class Meta:
"""Meta class."""
model = models.Company
fields = [
'id',
'establishment',
'name',
'phones',
'faxes',
'legal_entity',
'registry_number',
'vat_number',
'sic_code',
'address',
'phone_list',
'fax_list',
'address_detail',
]
extra_kwargs = {
'establishment': {'write_only': True},
'phones': {'write_only': True},
'faxes': {'write_only': True},
'address': {'write_only': True}
}
def get_phone_list(self, instance):
return instance.phones
def get_fax_list(self, instance):
return instance.faxes

View File

@ -13,6 +13,15 @@ urlpatterns = [
name='schedule-rud'), name='schedule-rud'),
path('<int:pk>/schedule/', views.EstablishmentScheduleCreateView.as_view(), path('<int:pk>/schedule/', views.EstablishmentScheduleCreateView.as_view(),
name='schedule-create'), name='schedule-create'),
path('<int:pk>/gallery/', views.EstablishmentGalleryListView.as_view(),
name='gallery-list'),
path('<int:pk>/gallery/<int:image_id>/',
views.EstablishmentGalleryCreateDestroyView.as_view(),
name='gallery-create-destroy'),
path('<int:pk>/companies/', views.EstablishmentCompanyListCreateView.as_view(),
name='company-list-create'),
path('<int:pk>/companies/<int:company_pk>/', views.EstablishmentCompanyRUDView.as_view(),
name='company-rud'),
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('plates/', views.PlateListCreateView.as_view(), name='plates'), path('plates/', views.PlateListCreateView.as_view(), name='plates'),
@ -31,11 +40,4 @@ urlpatterns = [
path('types/<int:pk>/', views.EstablishmentTypeRUDView.as_view(), name='type-rud'), path('types/<int:pk>/', views.EstablishmentTypeRUDView.as_view(), name='type-rud'),
path('subtypes/', views.EstablishmentSubtypeListCreateView.as_view(), name='subtype-list'), path('subtypes/', views.EstablishmentSubtypeListCreateView.as_view(), name='subtype-list'),
path('subtypes/<int:pk>/', views.EstablishmentSubtypeRUDView.as_view(), name='subtype-rud'), path('subtypes/<int:pk>/', views.EstablishmentSubtypeRUDView.as_view(), name='subtype-rud'),
# gallery
path('<int:pk>/gallery/', views.EstablishmentBackOfficeGalleryListView.as_view(),
name='gallery-list'),
path('<int:pk>/gallery/<int:image_id>/',
views.EstablishmentBackOfficeGalleryCreateDestroyView.as_view(),
name='gallery-create-destroy'),
] ]

View File

@ -6,6 +6,8 @@ from establishment import filters, models, serializers
from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer
from utils.permissions import IsCountryAdmin, IsEstablishmentManager from utils.permissions import IsCountryAdmin, IsEstablishmentManager
from utils.views import CreateDestroyGalleryViewMixin from utils.views import CreateDestroyGalleryViewMixin
from rest_framework import status
from rest_framework.response import Response
class EstablishmentMixinViews: class EstablishmentMixinViews:
@ -187,8 +189,8 @@ class EstablishmentSubtypeRUDView(generics.RetrieveUpdateDestroyAPIView):
queryset = models.EstablishmentSubType.objects.all() queryset = models.EstablishmentSubType.objects.all()
class EstablishmentBackOfficeGalleryCreateDestroyView(EstablishmentMixinViews, class EstablishmentGalleryCreateDestroyView(EstablishmentMixinViews,
CreateDestroyGalleryViewMixin): CreateDestroyGalleryViewMixin):
"""Resource for a create|destroy gallery for product for back-office users.""" """Resource for a create|destroy gallery for product for back-office users."""
serializer_class = serializers.EstablishmentBackOfficeGallerySerializer serializer_class = serializers.EstablishmentBackOfficeGallerySerializer
@ -207,14 +209,14 @@ class EstablishmentBackOfficeGalleryCreateDestroyView(EstablishmentMixinViews,
return gallery return gallery
class EstablishmentBackOfficeGalleryListView(EstablishmentMixinViews, class EstablishmentGalleryListView(EstablishmentMixinViews,
generics.ListAPIView): generics.ListAPIView):
"""Resource for returning gallery for establishment for back-office users.""" """Resource for returning gallery for establishment for back-office users."""
serializer_class = serializers.ImageBaseSerializer serializer_class = serializers.ImageBaseSerializer
def get_object(self): def get_object(self):
"""Override get_object method.""" """Override get_object method."""
qs = super(EstablishmentBackOfficeGalleryListView, self).get_queryset() qs = super(EstablishmentGalleryListView, self).get_queryset()
establishment = get_object_or_404(qs, pk=self.kwargs['pk']) establishment = get_object_or_404(qs, pk=self.kwargs['pk'])
# May raise a permission denied # May raise a permission denied
@ -225,3 +227,47 @@ class EstablishmentBackOfficeGalleryListView(EstablishmentMixinViews,
def get_queryset(self): def get_queryset(self):
"""Override get_queryset method.""" """Override get_queryset method."""
return self.get_object().crop_gallery return self.get_object().crop_gallery
class EstablishmentCompanyListCreateView(EstablishmentMixinViews,
generics.ListCreateAPIView):
"""List|Create establishment company view."""
serializer_class = serializers.EstablishmentCompanyListCreateSerializer
def get_object(self):
"""Returns the object the view is displaying."""
establishment_qs = models.Establishment.objects.all()
filtered_ad_qs = self.filter_queryset(establishment_qs)
establishment = get_object_or_404(filtered_ad_qs, pk=self.kwargs['pk'])
# May raise a permission denied
self.check_object_permissions(self.request, establishment)
return establishment
def get_queryset(self):
"""Overridden get_queryset method."""
return self.get_object().companies.all()
class EstablishmentCompanyRUDView(EstablishmentMixinViews,
generics.RetrieveUpdateDestroyAPIView):
"""Create|Retrieve|Update|Destroy establishment company view."""
serializer_class = serializers.CompanyBaseSerializer
def get_object(self):
"""Returns the object the view is displaying."""
establishment_qs = models.Establishment.objects.all()
filtered_ad_qs = self.filter_queryset(establishment_qs)
establishment = get_object_or_404(filtered_ad_qs, pk=self.kwargs['pk'])
company = get_object_or_404(establishment.companies.all(), pk=self.kwargs['company_pk'])
# May raise a permission denied
self.check_object_permissions(self.request, company)
return company

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.7 on 2019-11-18 13:13
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('location', '0026_country_is_active'),
]
operations = [
migrations.AlterField(
model_name='winesubregion',
name='wine_region',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='wine_sub_region', to='location.WineRegion', verbose_name='wine sub region'),
),
]

View File

@ -40,3 +40,8 @@ class CarouselAdmin(admin.ModelAdmin):
@admin.register(models.PageType) @admin.register(models.PageType)
class PageTypeAdmin(admin.ModelAdmin): class PageTypeAdmin(admin.ModelAdmin):
"""PageType admin.""" """PageType admin."""
@admin.register(models.Page)
class PageAdmin(admin.ModelAdmin):
"""Page admin."""