Merge remote-tracking branch 'origin/develop' into feature/reviews

# Conflicts:
#	apps/establishment/admin.py
#	apps/establishment/models.py
#	apps/establishment/serializers.py
This commit is contained in:
Anatoly 2019-09-01 13:38:40 +03:00
commit de8db655ed
13 changed files with 303 additions and 18 deletions

View File

@ -27,6 +27,29 @@ class MetaDataContentInline(GenericTabularInline):
extra = 0 extra = 0
class ContactPhoneInline(admin.TabularInline):
"""Contact phone inline admin."""
model = models.ContactPhone
extra = 0
class ContactEmailInline(admin.TabularInline):
"""Contact email inline admin."""
model = models.ContactEmail
extra = 0
@admin.register(models.Contact)
class ContactAdmin(admin.ModelAdmin):
"""Contact admin."""
inlines = [ContactPhoneInline, ContactEmailInline, ]
class ContactsInline(admin.TabularInline):
model = models.Contact
extra = 0
class ReviewInline(GenericTabularInline): class ReviewInline(GenericTabularInline):
model = review_models.Review model = review_models.Review
extra = 0 extra = 0
@ -35,7 +58,7 @@ class ReviewInline(GenericTabularInline):
@admin.register(models.Establishment) @admin.register(models.Establishment)
class EstablishmentAdmin(admin.ModelAdmin): class EstablishmentAdmin(admin.ModelAdmin):
"""Establishment admin.""" """Establishment admin."""
inlines = [AwardInline, MetaDataContentInline, ReviewInline] inlines = [AwardInline, MetaDataContentInline, ContactsInline, ReviewInline]
@admin.register(models.EstablishmentSchedule) @admin.register(models.EstablishmentSchedule)

View File

@ -0,0 +1,77 @@
# Generated by Django 2.2.4 on 2019-09-01 08:31
from django.db import migrations, models
import django.db.models.deletion
import phonenumber_field.modelfields
import utils.models
class Migration(migrations.Migration):
dependencies = [
('location', '0009_auto_20190901_0831'),
('establishment', '0004_auto_20190828_1156'),
]
operations = [
migrations.CreateModel(
name='Contact',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='location.Address')),
],
options={
'verbose_name': 'contact',
'verbose_name_plural': 'contacts',
},
),
migrations.AlterField(
model_name='establishment',
name='description',
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='Description'),
),
migrations.AlterField(
model_name='establishment',
name='name',
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='Name'),
),
migrations.AlterField(
model_name='establishmentsubtype',
name='name',
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='Description'),
),
migrations.AlterField(
model_name='establishmenttype',
name='name',
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='Description'),
),
migrations.CreateModel(
name='ContactPhone',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('phone', phonenumber_field.modelfields.PhoneNumberField(max_length=128)),
('contact', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='phones', to='establishment.Contact')),
],
options={
'verbose_name': 'contact phone',
'verbose_name_plural': 'contact phones',
},
),
migrations.CreateModel(
name='ContactEmail',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('email', models.EmailField(max_length=254)),
('contact', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='emails', to='establishment.Contact')),
],
options={
'verbose_name': 'contact email',
'verbose_name_plural': 'contact emails',
},
),
migrations.AddField(
model_name='contact',
name='establishment',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contacts', to='establishment.Establishment'),
),
]

View File

@ -0,0 +1,14 @@
# Generated by Django 2.2.4 on 2019-09-01 08:46
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('establishment', '0005_auto_20190901_0831'),
('establishment', '0005_establishmentschedule'),
]
operations = [
]

View File

@ -1,14 +1,15 @@
"""Establishment models.""" """Establishment models."""
from functools import reduce
from django.contrib.contenttypes import fields as generic from django.contrib.contenttypes import fields as generic
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from phonenumber_field.modelfields import PhoneNumberField
from location.models import Address from location.models import Address
from utils.models import (ProjectBaseMixin, ImageMixin, TJSONField, from utils.models import (
TraslatedFieldsMixin, BaseAttributes) ProjectBaseMixin, ImageMixin, TJSONField,
TraslatedFieldsMixin, BaseAttributes
)
# todo: establishment type&subtypes check # todo: establishment type&subtypes check
@ -16,7 +17,7 @@ class EstablishmentType(ProjectBaseMixin, TraslatedFieldsMixin):
"""Establishment type model.""" """Establishment type model."""
name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'), name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'),
help_text='{"en":"some text"}') help_text='{"en-GB":"some text"}')
use_subtypes = models.BooleanField(_('Use subtypes'), default=True) use_subtypes = models.BooleanField(_('Use subtypes'), default=True)
class Meta: class Meta:
@ -40,7 +41,7 @@ class EstablishmentSubType(ProjectBaseMixin, TraslatedFieldsMixin):
"""Establishment type model.""" """Establishment type model."""
name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'), name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'),
help_text='{"en":"some text"}') help_text='{"en-GB":"some text"}')
establishment_type = models.ForeignKey(EstablishmentType, establishment_type = models.ForeignKey(EstablishmentType,
on_delete=models.CASCADE, on_delete=models.CASCADE,
verbose_name=_('Type')) verbose_name=_('Type'))
@ -77,10 +78,10 @@ class Establishment(ProjectBaseMixin, ImageMixin, TraslatedFieldsMixin):
"""Establishment model.""" """Establishment model."""
name = TJSONField(blank=True, null=True, default=None, name = TJSONField(blank=True, null=True, default=None,
verbose_name=_('Name'), help_text='{"en":"some text"}') verbose_name=_('Name'), help_text='{"en-GB":"some text"}')
description = TJSONField(blank=True, null=True, default=None, description = TJSONField(blank=True, null=True, default=None,
verbose_name=_('Description'), verbose_name=_('Description'),
help_text='{"en":"some text"}') help_text='{"en-GB":"some text"}')
public_mark = models.PositiveIntegerField(blank=True, null=True, public_mark = models.PositiveIntegerField(blank=True, null=True,
default=None, default=None,
verbose_name=_('Public mark'),) verbose_name=_('Public mark'),)
@ -163,3 +164,106 @@ class EstablishmentSchedule(BaseAttributes):
"""Meta class""" """Meta class"""
verbose_name = _('Establishment schedule') verbose_name = _('Establishment schedule')
verbose_name_plural = _('Establishment schedules') verbose_name_plural = _('Establishment schedules')
class Contact(models.Model):
"""Contact model."""
establishment = models.ForeignKey(
Establishment, related_name='contacts', on_delete=models.CASCADE)
address = models.ForeignKey('location.Address', on_delete=models.CASCADE)
class Meta:
verbose_name = _('contact')
verbose_name_plural = _('contacts')
class ContactPhone(models.Model):
"""Contact phone model."""
contact = models.ForeignKey(
Contact, related_name='phones', on_delete=models.CASCADE)
phone = PhoneNumberField()
class Meta:
verbose_name = _('contact phone')
verbose_name_plural = _('contact phones')
def __str__(self):
return f'{self.phone.as_e164}'
class ContactEmail(models.Model):
"""Contact email model."""
contact = models.ForeignKey(
Contact, related_name='emails', on_delete=models.CASCADE)
email = models.EmailField()
class Meta:
verbose_name = _('contact email')
verbose_name_plural = _('contact emails')
def __str__(self):
return f'{self.email}'
#
# class Wine(TraslatedFieldsMixin, models.Model):
# """Wine model."""
# establishment = models.ForeignKey(
# 'establishment.Establishment', verbose_name=_('establishment'),
# on_delete=models.CASCADE)
# bottles = models.IntegerField(_('bottles'))
# price_min = models.DecimalField(
# _('price min'), max_digits=14, decimal_places=2)
# price_max = models.DecimalField(
# _('price max'), max_digits=14, decimal_places=2)
# by_glass = models.BooleanField(_('by glass'))
# price_glass_min = models.DecimalField(
# _('price min'), max_digits=14, decimal_places=2)
# price_glass_max = models.DecimalField(
# _('price max'), max_digits=14, decimal_places=2)
#
#
# class Plate(TraslatedFieldsMixin, models.Model):
# """Plate model."""
#
# STARTER = 0
# MAIN = 1
# COURSE = 2
# DESSERT = 3
#
# PLATE_TYPE_CHOICES = (
# (STARTER, _('starter')),
# (MAIN, _('main')),
# (COURSE, _('course')),
# (DESSERT, _('dessert')),
# )
# name = models.CharField(_('name'), max_length=255)
# plate_type = models.PositiveSmallIntegerField(_('plate_type'), choices=PLATE_TYPE_CHOICES)
# description = TJSONField(
# blank=True, null=True, default=None, verbose_name=_('description'),
# help_text='{"en-GB":"some text"}')
# price = models.DecimalField(
# _('price'), max_digits=14, decimal_places=2)
# is_signature_plate = models.BooleanField(_('is signature plate'))
# currency = models.ForeignKey(
# 'main.Currency', verbose_name=_('currency'), on_delete=models.CASCADE)
#
# menu = models.ManyToManyField(to='Plate', verbose_name=_(''), through='establishment.Menu')
#
# class Meta:
# verbose_name = _('plate')
# verbose_name_plural = _('plates')
#
# def __str__(self):
# return f'plate_id:{self.id}'
#
#
# class Menu(TraslatedFieldsMixin, BaseAttributes):
# """Menu model."""
# establishment = models.ForeignKey(
# 'establishment.Establishment', verbose_name=_('establishment'),
# on_delete=models.CASCADE)
# plate = models.ForeignKey(Plate, verbose_name=_('menu'), on_delete=models.CASCADE)
#
# class Meta:
# verbose_name = _('menu')
# verbose_name_plural = _('menu')

View File

@ -1,6 +1,5 @@
"""Establishment serializers.""" """Establishment serializers."""
from rest_framework import serializers from rest_framework import serializers
from establishment import models from establishment import models
from location.serializers import AddressSerializer from location.serializers import AddressSerializer
from main.serializers import MetaDataContentSerializer, AwardSerializer from main.serializers import MetaDataContentSerializer, AwardSerializer
@ -8,6 +7,39 @@ from review import models as review_models
from timetable.models import Timetable from timetable.models import Timetable
class ContactPhonesSerializer(serializers.ModelSerializer):
"""Contact phone serializer"""
class Meta:
model = models.ContactPhone
fields = [
'phone'
]
class ContactEmailsSerializer(serializers.ModelSerializer):
"""Contact email serializer"""
class Meta:
model = models.ContactEmail
fields = [
'email'
]
class ContactSerializer(serializers.ModelSerializer):
"""Contact serializer."""
address = AddressSerializer(read_only=True)
phones = ContactPhonesSerializer(read_only=True, many=True,)
emails = ContactEmailsSerializer(read_only=True, many=True,)
class Meta:
model = models.Contact
fields = [
'address',
'phones',
'emails'
]
class EstablishmentTypeSerializer(serializers.ModelSerializer): class EstablishmentTypeSerializer(serializers.ModelSerializer):
"""Serializer for EstablishmentType model.""" """Serializer for EstablishmentType model."""
@ -71,6 +103,7 @@ class EstablishmentSerializer(serializers.ModelSerializer):
schedule = EstablishmentScheduleSerializer(source='schedule.schedule', schedule = EstablishmentScheduleSerializer(source='schedule.schedule',
many=True, many=True,
allow_null=True) allow_null=True)
contacts = ContactSerializer(read_only=True, many=True, )
reviews = ReviewSerializer(source='reviews.last', reviews = ReviewSerializer(source='reviews.last',
allow_null=True) allow_null=True)
@ -94,4 +127,5 @@ class EstablishmentSerializer(serializers.ModelSerializer):
'awards', 'awards',
'schedule', 'schedule',
'reviews', 'reviews',
'contacts'
) )

View File

@ -30,6 +30,6 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='country', model_name='country',
name='name', name='name',
field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=None, help_text='{"en":"some text"}', null=True, verbose_name='Text'), field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='Text'),
), ),
] ]

View File

@ -0,0 +1,19 @@
# Generated by Django 2.2.4 on 2019-09-01 08:31
import django.contrib.postgres.fields.jsonb
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('location', '0008_auto_20190827_1302'),
]
operations = [
migrations.AlterField(
model_name='country',
name='name',
field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='Name'),
),
]

View File

@ -17,7 +17,7 @@ class Country(SVGImageMixin, ProjectBaseMixin):
"""Country model.""" """Country model."""
name = JSONField(null=True, blank=True, default=None, name = JSONField(null=True, blank=True, default=None,
verbose_name=_('Name'), help_text='{"en":"some text"}') verbose_name=_('Name'), help_text='{"en-GB":"some text"}')
code = models.CharField(max_length=255, unique=True, verbose_name=_('Code')) code = models.CharField(max_length=255, unique=True, verbose_name=_('Code'))
low_price = models.IntegerField(default=25, verbose_name=_('Low price')) low_price = models.IntegerField(default=25, verbose_name=_('Low price'))
high_price = models.IntegerField(default=50, verbose_name=_('High price')) high_price = models.IntegerField(default=50, verbose_name=_('High price'))

View File

@ -190,7 +190,7 @@ class Award(TraslatedFieldsMixin, models.Model):
award_type = models.ForeignKey('main.AwardType', on_delete=models.CASCADE) award_type = models.ForeignKey('main.AwardType', on_delete=models.CASCADE)
title = TJSONField( title = TJSONField(
_('title'), null=True, blank=True, _('title'), null=True, blank=True,
default=None, help_text='{"en":"some text"}') default=None, help_text='{"en-GB":"some text"}')
vintage_year = models.CharField(_('vintage year'), max_length=255, default='') vintage_year = models.CharField(_('vintage year'), max_length=255, default='')
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
@ -228,7 +228,7 @@ class MetaData(TraslatedFieldsMixin, models.Model):
"""MetaData model.""" """MetaData model."""
label = TJSONField( label = TJSONField(
_('label'), null=True, blank=True, _('label'), null=True, blank=True,
default=None, help_text='{"en":"some text"}') default=None, help_text='{"en-GB":"some text"}')
category = models.ForeignKey( category = models.ForeignKey(
MetaDataCategory, verbose_name=_('category'), on_delete=models.CASCADE) MetaDataCategory, verbose_name=_('category'), on_delete=models.CASCADE)
@ -250,3 +250,15 @@ class MetaDataContent(models.Model):
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id') content_object = generic.GenericForeignKey('content_type', 'object_id')
metadata = models.ForeignKey(MetaData, on_delete=models.CASCADE) metadata = models.ForeignKey(MetaData, on_delete=models.CASCADE)
class Currency(models.Model):
"""Currency model."""
name = models.CharField(_('name'), max_length=50)
class Meta:
verbose_name = _('currency')
verbose_name_plural = _('currencies')
def __str__(self):
return f'{self.name}'

View File

@ -43,14 +43,14 @@ class News(BaseAttributes, TraslatedFieldsMixin):
title = TJSONField( title = TJSONField(
_('title'), null=True, blank=True, _('title'), null=True, blank=True,
default=None, help_text='{"en":"some text"}') default=None, help_text='{"en-GB":"some text"}')
subtitle = TJSONField( subtitle = TJSONField(
_('subtitle'), null=True, blank=True, _('subtitle'), null=True, blank=True,
default=None, help_text='{"en":"some text"}' default=None, help_text='{"en-GB":"some text"}'
) )
description = TJSONField( description = TJSONField(
_('description'), null=True, blank=True, _('description'), null=True, blank=True,
default=None, help_text='{"en":"some text"}' default=None, help_text='{"en-GB":"some text"}'
) )
start = models.DateTimeField(_('start')) start = models.DateTimeField(_('start'))
end = models.DateTimeField(_('end')) end = models.DateTimeField(_('end'))

View File

@ -49,7 +49,7 @@ class SiteInterfaceDictionary(ProjectBaseMixin):
verbose_name=_('Page')) verbose_name=_('Page'))
keywords = models.CharField(max_length=255, verbose_name='Keywords') keywords = models.CharField(max_length=255, verbose_name='Keywords')
text = JSONField(_('Text'), null=True, blank=True, text = JSONField(_('Text'), null=True, blank=True,
default=None, help_text='{"en":"some text"}') default=None, help_text='{"en-GB":"some text"}')
objects = SiteInterfaceDictionaryManager() objects = SiteInterfaceDictionaryManager()

View File

@ -83,6 +83,7 @@ EXTERNAL_APPS = [
'django_extensions', 'django_extensions',
'rest_framework_simplejwt.token_blacklist', 'rest_framework_simplejwt.token_blacklist',
'solo', 'solo',
'phonenumber_field',
] ]

View File

@ -17,6 +17,7 @@ djangorestframework-xml
celery celery
amqp>=2.4.0 amqp>=2.4.0
geoip2==2.9.0 geoip2==2.9.0
django-phonenumber-field[phonenumbers]==2.1.0
# auth socials # auth socials
djangorestframework-oauth djangorestframework-oauth