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):
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
def mobile_page(self):
"""Return mobile page"""

View File

@ -9,9 +9,9 @@ app_name = 'advertisements'
urlpatterns = [
path('', views.AdvertisementListCreateView.as_view(), name='list-create'),
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'),
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')
]

View File

@ -33,14 +33,6 @@ class AdvertisementRUDView(AdvertisementBackOfficeViewMixin,
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,
generics.ListCreateAPIView):
@ -66,7 +58,6 @@ class AdvertisementPageListCreateView(AdvertisementBackOfficeViewMixin,
class AdvertisementPageRUDView(AdvertisementBackOfficeViewMixin,
generics.CreateAPIView,
generics.RetrieveUpdateDestroyAPIView):
"""Create|Retrieve|Update|Destroy advertisement page view."""

View File

@ -59,13 +59,18 @@ class ProductInline(admin.TabularInline):
extra = 0
class CompanyInline(admin.TabularInline):
model = models.Company
extra = 0
@admin.register(models.Establishment)
class EstablishmentAdmin(BaseModelAdminMixin, admin.ModelAdmin):
"""Establishment admin."""
list_display = ['id', '__str__', 'image_tag', ]
search_fields = ['id', 'name', 'index_name', 'slug']
list_filter = ['public_mark', 'toque_number']
inlines = [GalleryImageInline, ]
inlines = [GalleryImageInline, CompanyInline]
# inlines = [
# AwardInline, ContactPhoneInline, ContactEmailInline,
@ -114,3 +119,9 @@ class SocialChoiceAdmin(BaseModelAdminMixin, admin.ModelAdmin):
class SocialNetworkAdmin(BaseModelAdminMixin, admin.ModelAdmin):
"""Admin conf for SocialNetwork model."""
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 phonenumber_field.modelfields import PhoneNumberField
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 location.models import Address
@ -408,6 +410,12 @@ class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin, Translat
def __str__(self):
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
def visible_tags(self):
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"}. ' \
f'"{self.toque_number}": {self.public_mark_min_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 establishment import models
from establishment.serializers import (
EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer,
ContactPhonesSerializer, SocialNetworkRelatedSerializers,
EstablishmentTypeBaseSerializer)
from establishment import serializers as model_serializers
from location.serializers import AddressDetailSerializer
from main.models import Currency
from utils.decorators import with_base_attributes
@ -13,17 +10,22 @@ from gallery.models import Image
from django.utils.translation import gettext_lazy as _
class EstablishmentListCreateSerializer(EstablishmentBaseSerializer):
class EstablishmentListCreateSerializer(model_serializers.EstablishmentBaseSerializer):
"""Establishment create serializer"""
type_id = serializers.PrimaryKeyRelatedField(
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, )
emails = ContactEmailsSerializer(read_only=True, many=True, )
socials = SocialNetworkRelatedSerializers(read_only=True, many=True, )
type = EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True)
phones = model_serializers.ContactPhonesSerializer(read_only=True,
many=True, )
emails = model_serializers.ContactEmailsSerializer(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()
class Meta:
@ -52,7 +54,7 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer):
]
class EstablishmentRUDSerializer(EstablishmentBaseSerializer):
class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
"""Establishment create serializer"""
type_id = serializers.PrimaryKeyRelatedField(
@ -60,10 +62,13 @@ class EstablishmentRUDSerializer(EstablishmentBaseSerializer):
queryset=models.EstablishmentType.objects.all(), write_only=True
)
address = AddressDetailSerializer()
phones = ContactPhonesSerializer(read_only=False, many=True, )
emails = ContactEmailsSerializer(read_only=False, many=True, )
socials = SocialNetworkRelatedSerializers(read_only=False, many=True, )
type = EstablishmentTypeBaseSerializer(source='establishment_type')
phones = model_serializers.ContactPhonesSerializer(read_only=False,
many=True, )
emails = model_serializers.ContactEmailsSerializer(read_only=False,
many=True, )
socials = model_serializers.SocialNetworkRelatedSerializers(read_only=False,
many=True, )
type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type')
class Meta:
model = models.Establishment
@ -107,7 +112,7 @@ class SocialNetworkSerializers(serializers.ModelSerializer):
]
class PlatesSerializers(PlateSerializer):
class PlatesSerializers(model_serializers.PlateSerializer):
"""Plates serializers."""
currency_id = serializers.PrimaryKeyRelatedField(
@ -119,14 +124,14 @@ class PlatesSerializers(PlateSerializer):
"""Meta class."""
model = models.Plate
fields = PlateSerializer.Meta.fields + [
fields = model_serializers.PlateSerializer.Meta.fields + [
'name',
'currency_id',
'menu'
]
class ContactPhoneBackSerializers(PlateSerializer):
class ContactPhoneBackSerializers(model_serializers.PlateSerializer):
"""ContactPhone serializers."""
class Meta:
@ -138,7 +143,7 @@ class ContactPhoneBackSerializers(PlateSerializer):
]
class ContactEmailBackSerializers(PlateSerializer):
class ContactEmailBackSerializers(model_serializers.PlateSerializer):
"""ContactEmail serializers."""
class Meta:
@ -204,3 +209,18 @@ class EstablishmentBackOfficeGallerySerializer(serializers.ModelSerializer):
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)

View File

@ -2,6 +2,7 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from phonenumber_field.modelfields import PhoneNumberField
from comment import models as comment_models
from comment.serializers import common as comment_serializers
from establishment import models
@ -418,3 +419,41 @@ class EstablishmentFavoritesCreateSerializer(FavoritesCreateSerializer):
'content_object': validated_data.pop('establishment')
})
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'),
path('<int:pk>/schedule/', views.EstablishmentScheduleCreateView.as_view(),
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/<int:pk>/', views.MenuRUDView.as_view(), name='menu-rud'),
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('subtypes/', views.EstablishmentSubtypeListCreateView.as_view(), name='subtype-list'),
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 utils.permissions import IsCountryAdmin, IsEstablishmentManager
from utils.views import CreateDestroyGalleryViewMixin
from rest_framework import status
from rest_framework.response import Response
class EstablishmentMixinViews:
@ -187,8 +189,8 @@ class EstablishmentSubtypeRUDView(generics.RetrieveUpdateDestroyAPIView):
queryset = models.EstablishmentSubType.objects.all()
class EstablishmentBackOfficeGalleryCreateDestroyView(EstablishmentMixinViews,
CreateDestroyGalleryViewMixin):
class EstablishmentGalleryCreateDestroyView(EstablishmentMixinViews,
CreateDestroyGalleryViewMixin):
"""Resource for a create|destroy gallery for product for back-office users."""
serializer_class = serializers.EstablishmentBackOfficeGallerySerializer
@ -207,14 +209,14 @@ class EstablishmentBackOfficeGalleryCreateDestroyView(EstablishmentMixinViews,
return gallery
class EstablishmentBackOfficeGalleryListView(EstablishmentMixinViews,
generics.ListAPIView):
class EstablishmentGalleryListView(EstablishmentMixinViews,
generics.ListAPIView):
"""Resource for returning gallery for establishment for back-office users."""
serializer_class = serializers.ImageBaseSerializer
def get_object(self):
"""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'])
# May raise a permission denied
@ -225,3 +227,47 @@ class EstablishmentBackOfficeGalleryListView(EstablishmentMixinViews,
def get_queryset(self):
"""Override get_queryset method."""
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)
class PageTypeAdmin(admin.ModelAdmin):
"""PageType admin."""
@admin.register(models.Page)
class PageAdmin(admin.ModelAdmin):
"""Page admin."""