Merge remote-tracking branch 'origin/develop' into feature/authorization
This commit is contained in:
commit
3c7fc7a436
|
|
@ -18,7 +18,7 @@ class UserAdmin(BaseUserAdmin):
|
|||
fieldsets = (
|
||||
(None, {'fields': ('email', 'password',)}),
|
||||
(_('Personal info'), {
|
||||
'fields': ('username', 'first_name', 'last_name', )}),
|
||||
'fields': ('username', 'first_name', 'last_name', 'image')}),
|
||||
(_('Subscription'), {
|
||||
'fields': (
|
||||
'newsletter',
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
"""Establishment admin conf."""
|
||||
from django.contrib import admin
|
||||
from establishment import models
|
||||
from django.contrib.contenttypes.admin import GenericTabularInline
|
||||
from establishment import models
|
||||
from main.models import Award, MetaDataContent
|
||||
from review import models as review_models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
@admin.register(models.EstablishmentType)
|
||||
|
|
@ -25,12 +27,63 @@ class MetaDataContentInline(GenericTabularInline):
|
|||
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
|
||||
|
||||
|
||||
class ReviewInline(GenericTabularInline):
|
||||
model = review_models.Review
|
||||
extra = 0
|
||||
|
||||
|
||||
@admin.register(models.Establishment)
|
||||
class EstablishmentAdmin(admin.ModelAdmin):
|
||||
"""Establishment admin."""
|
||||
inlines = [AwardInline, MetaDataContentInline]
|
||||
inlines = [
|
||||
AwardInline, MetaDataContentInline,
|
||||
ContactPhoneInline, ContactEmailInline,
|
||||
ReviewInline]
|
||||
|
||||
|
||||
@admin.register(models.EstablishmentSchedule)
|
||||
class EstablishmentSchedule(admin.ModelAdmin):
|
||||
"""Establishment schedule"""
|
||||
|
||||
|
||||
@admin.register(models.Comment)
|
||||
class EstablishmentComment(admin.ModelAdmin):
|
||||
"""Establishment comments."""
|
||||
|
||||
|
||||
@admin.register(models.Position)
|
||||
class PositionAdmin(admin.ModelAdmin):
|
||||
"""Position admin."""
|
||||
|
||||
|
||||
class PlateInline(admin.TabularInline):
|
||||
"""Plate inline admin"""
|
||||
model = models.Plate
|
||||
extra = 0
|
||||
|
||||
|
||||
@admin.register(models.Menu)
|
||||
class MenuAdmin(admin.ModelAdmin):
|
||||
"""Menu admin."""
|
||||
list_display = ['id', 'category_translated']
|
||||
inlines = [
|
||||
PlateInline,
|
||||
]
|
||||
|
||||
def category_translated(self, obj):
|
||||
"""Get user's short name."""
|
||||
return obj.category_translated
|
||||
|
||||
category_translated.short_description = _('category')
|
||||
77
apps/establishment/migrations/0005_auto_20190901_0831.py
Normal file
77
apps/establishment/migrations/0005_auto_20190901_0831.py
Normal 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'),
|
||||
),
|
||||
]
|
||||
32
apps/establishment/migrations/0006_comment.py
Normal file
32
apps/establishment/migrations/0006_comment.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 09:16
|
||||
|
||||
import django.utils.timezone
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('establishment', '0005_establishmentschedule'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Comment',
|
||||
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')),
|
||||
('text', models.TextField(verbose_name='Comment text')),
|
||||
('mark', models.PositiveIntegerField(blank=True, default=None, null=True, verbose_name='Mark')),
|
||||
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to=settings.AUTH_USER_MODEL, verbose_name='Author')),
|
||||
('establishment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='establishment.Establishment', verbose_name='Establishment')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Comment',
|
||||
'verbose_name_plural': 'Comments',
|
||||
},
|
||||
),
|
||||
]
|
||||
14
apps/establishment/migrations/0006_merge_20190901_0846.py
Normal file
14
apps/establishment/migrations/0006_merge_20190901_0846.py
Normal 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 = [
|
||||
]
|
||||
30
apps/establishment/migrations/0007_auto_20190901_1032.py
Normal file
30
apps/establishment/migrations/0007_auto_20190901_1032.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 10:32
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0006_merge_20190901_0846'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='contactemail',
|
||||
name='contact',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='contactphone',
|
||||
name='contact',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Contact',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='ContactEmail',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='ContactPhone',
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 10:36
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import phonenumber_field.modelfields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0007_auto_20190901_1032'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
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)),
|
||||
('establishment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='phones', to='establishment.Establishment')),
|
||||
],
|
||||
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)),
|
||||
('establishment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='emails', to='establishment.Establishment')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'contact email',
|
||||
'verbose_name_plural': 'contact emails',
|
||||
},
|
||||
),
|
||||
]
|
||||
14
apps/establishment/migrations/0009_merge_20190901_1131.py
Normal file
14
apps/establishment/migrations/0009_merge_20190901_1131.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 11:31
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0006_comment'),
|
||||
('establishment', '0008_contactemail_contactphone'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
||||
81
apps/establishment/migrations/0010_auto_20190901_1142.py
Normal file
81
apps/establishment/migrations/0010_auto_20190901_1142.py
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 11:42
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('establishment', '0009_merge_20190901_1131'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Employee',
|
||||
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='Last name')),
|
||||
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='employee_records_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Employee',
|
||||
'verbose_name_plural': 'Employees',
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Position',
|
||||
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', utils.models.TJSONField(blank=True, default=None, help_text='{"en":"some text"}', null=True, verbose_name='Description')),
|
||||
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='position_records_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
||||
('modified_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='position_records_modified', to=settings.AUTH_USER_MODEL, verbose_name='modified by')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Position',
|
||||
'verbose_name_plural': 'Positions',
|
||||
},
|
||||
bases=(models.Model, utils.models.TraslatedFieldsMixin),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='EstablishmentEmployee',
|
||||
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')),
|
||||
('from_date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='From date')),
|
||||
('to_date', models.DateTimeField(blank=True, default=None, null=True, verbose_name='To date')),
|
||||
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='establishmentemployee_records_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
||||
('employee', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='establishment.Employee', verbose_name='Employee')),
|
||||
('establishment', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='establishment.Establishment', verbose_name='Establishment')),
|
||||
('modified_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='establishmentemployee_records_modified', to=settings.AUTH_USER_MODEL, verbose_name='modified by')),
|
||||
('position', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='establishment.Position', verbose_name='Position')),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='employee',
|
||||
name='establishments',
|
||||
field=models.ManyToManyField(related_name='employees', through='establishment.EstablishmentEmployee', to='establishment.Establishment'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='employee',
|
||||
name='modified_by',
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='employee_records_modified', to=settings.AUTH_USER_MODEL, verbose_name='modified by'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='employee',
|
||||
name='user',
|
||||
field=models.OneToOneField(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='User'),
|
||||
),
|
||||
]
|
||||
53
apps/establishment/migrations/0011_menu_plate.py
Normal file
53
apps/establishment/migrations/0011_menu_plate.py
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 12:11
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('main', '0013_auto_20190901_1032'),
|
||||
('establishment', '0010_auto_20190901_1142'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Menu',
|
||||
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')),
|
||||
('category', utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='name')),
|
||||
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='menu_records_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
||||
('establishment', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='establishment.Establishment', verbose_name='establishment')),
|
||||
('modified_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='menu_records_modified', to=settings.AUTH_USER_MODEL, verbose_name='modified by')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'menu',
|
||||
'verbose_name_plural': 'menu',
|
||||
},
|
||||
bases=(utils.models.TraslatedFieldsMixin, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Plate',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='name')),
|
||||
('description', utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='description')),
|
||||
('price', models.DecimalField(decimal_places=2, max_digits=14, verbose_name='price')),
|
||||
('is_signature_plate', models.BooleanField(verbose_name='is signature plate')),
|
||||
('currency', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='main.Currency', verbose_name='currency')),
|
||||
('menu', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='establishment.Menu', verbose_name='menu')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'plate',
|
||||
'verbose_name_plural': 'plates',
|
||||
},
|
||||
bases=(utils.models.TraslatedFieldsMixin, models.Model),
|
||||
),
|
||||
]
|
||||
19
apps/establishment/migrations/0012_auto_20190901_1251.py
Normal file
19
apps/establishment/migrations/0012_auto_20190901_1251.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 12:51
|
||||
|
||||
from django.db import migrations
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0011_menu_plate'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='menu',
|
||||
name='category',
|
||||
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='category'),
|
||||
),
|
||||
]
|
||||
33
apps/establishment/migrations/0013_auto_20190901_1428.py
Normal file
33
apps/establishment/migrations/0013_auto_20190901_1428.py
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 14:28
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0012_auto_20190901_1251'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='establishment',
|
||||
name='booking',
|
||||
field=models.URLField(blank=True, default=None, null=True, verbose_name='Booking URL'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='establishment',
|
||||
name='facebook',
|
||||
field=models.URLField(blank=True, default=None, null=True, verbose_name='Facebook URL'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='establishment',
|
||||
name='lafourchette',
|
||||
field=models.URLField(blank=True, default=None, null=True, verbose_name='Lafourchette URL'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='establishment',
|
||||
name='twitter',
|
||||
field=models.URLField(blank=True, default=None, null=True, verbose_name='Twitter URL'),
|
||||
),
|
||||
]
|
||||
18
apps/establishment/migrations/0014_establishment_website.py
Normal file
18
apps/establishment/migrations/0014_establishment_website.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 14:48
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('establishment', '0013_auto_20190901_1428'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='establishment',
|
||||
name='website',
|
||||
field=models.URLField(blank=True, default=None, null=True, verbose_name='Web site URL'),
|
||||
),
|
||||
]
|
||||
|
|
@ -1,12 +1,16 @@
|
|||
"""Establishment models."""
|
||||
from functools import reduce
|
||||
|
||||
from django.contrib.contenttypes import fields as generic
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
|
||||
from location.models import Address
|
||||
from utils.models import (ProjectBaseMixin, ImageMixin, TJSONField,
|
||||
TraslatedFieldsMixin, BaseAttributes)
|
||||
from django.contrib.contenttypes import fields as generic
|
||||
|
||||
|
||||
# todo: establishment type&subtypes check
|
||||
|
|
@ -14,7 +18,7 @@ class EstablishmentType(ProjectBaseMixin, TraslatedFieldsMixin):
|
|||
"""Establishment type model."""
|
||||
|
||||
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)
|
||||
|
||||
class Meta:
|
||||
|
|
@ -38,7 +42,7 @@ class EstablishmentSubType(ProjectBaseMixin, TraslatedFieldsMixin):
|
|||
"""Establishment type model."""
|
||||
|
||||
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,
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_('Type'))
|
||||
|
|
@ -70,15 +74,27 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
else:
|
||||
return self.none()
|
||||
|
||||
def by_country_code(self, code):
|
||||
"""Return establishments by country code"""
|
||||
return self.filter(address__city__country__code=code)
|
||||
|
||||
def prefetch_actual_employees(self):
|
||||
"""Prefetch actual employees."""
|
||||
return self.prefetch_related(
|
||||
models.Prefetch('establishmentemployee_set',
|
||||
queryset=EstablishmentEmployee.objects.actual().select_related(
|
||||
'position'),
|
||||
to_attr='actual_establishment_employees'))
|
||||
|
||||
|
||||
class Establishment(ProjectBaseMixin, ImageMixin, TraslatedFieldsMixin):
|
||||
"""Establishment model."""
|
||||
|
||||
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,
|
||||
verbose_name=_('Description'),
|
||||
help_text='{"en":"some text"}')
|
||||
help_text='{"en-GB":"some text"}')
|
||||
public_mark = models.PositiveIntegerField(blank=True, null=True,
|
||||
default=None,
|
||||
verbose_name=_('Public mark'),)
|
||||
|
|
@ -98,8 +114,19 @@ class Establishment(ProjectBaseMixin, ImageMixin, TraslatedFieldsMixin):
|
|||
price_level = models.PositiveIntegerField(blank=True, null=True,
|
||||
default=None,
|
||||
verbose_name=_('Price level'))
|
||||
website = models.URLField(blank=True, null=True, default=None,
|
||||
verbose_name=_('Web site URL'))
|
||||
facebook = models.URLField(blank=True, null=True, default=None,
|
||||
verbose_name=_('Facebook URL'))
|
||||
twitter = models.URLField(blank=True, null=True, default=None,
|
||||
verbose_name=_('Twitter URL'))
|
||||
lafourchette = models.URLField(blank=True, null=True, default=None,
|
||||
verbose_name=_('Lafourchette URL'))
|
||||
booking = models.URLField(blank=True, null=True, default=None,
|
||||
verbose_name=_('Booking URL'))
|
||||
awards = generic.GenericRelation(to='main.Award')
|
||||
tags = generic.GenericRelation(to='main.MetaDataContent')
|
||||
reviews = generic.GenericRelation(to='review.Review')
|
||||
|
||||
objects = EstablishmentQuerySet.as_manager()
|
||||
|
||||
|
|
@ -123,6 +150,7 @@ class Establishment(ProjectBaseMixin, ImageMixin, TraslatedFieldsMixin):
|
|||
country = self.address.city.country
|
||||
return country.low_price, country.high_price
|
||||
|
||||
# todo: make via prefetch
|
||||
@property
|
||||
def subtypes(self):
|
||||
return EstablishmentSubType.objects.filter(
|
||||
|
|
@ -140,6 +168,73 @@ class Establishment(ProjectBaseMixin, ImageMixin, TraslatedFieldsMixin):
|
|||
raise ValidationError('Establishment type of subtype does not match')
|
||||
self.establishment_subtypes.add(establishment_subtype)
|
||||
|
||||
@property
|
||||
def best_price_menu(self):
|
||||
return 150
|
||||
|
||||
@property
|
||||
def best_price_carte(self):
|
||||
return 200
|
||||
|
||||
|
||||
class Position(BaseAttributes, TraslatedFieldsMixin):
|
||||
"""Position model."""
|
||||
|
||||
name = TJSONField(blank=True, null=True, default=None, verbose_name=_('Description'),
|
||||
help_text='{"en":"some text"}')
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
verbose_name = _('Position')
|
||||
verbose_name_plural = _('Positions')
|
||||
|
||||
|
||||
class EstablishmentEmployeeQuerySet(models.QuerySet):
|
||||
"""Extended queryset for EstablishmEntemployee model."""
|
||||
|
||||
def actual(self):
|
||||
"""Actual objects.."""
|
||||
now = timezone.now()
|
||||
return self.filter(models.Q(from_date__lte=now),
|
||||
(models.Q(to_date__gte=now) |
|
||||
models.Q(to_date__isnull=True)))
|
||||
|
||||
|
||||
class EstablishmentEmployee(BaseAttributes):
|
||||
"""EstablishmentEmployee model."""
|
||||
|
||||
establishment = models.ForeignKey(Establishment, on_delete=models.PROTECT,
|
||||
verbose_name=_('Establishment'))
|
||||
employee = models.ForeignKey('establishment.Employee', on_delete=models.PROTECT,
|
||||
verbose_name=_('Employee'))
|
||||
from_date = models.DateTimeField(default=timezone.now, verbose_name=_('From date'))
|
||||
to_date = models.DateTimeField(blank=True, null=True, default=None,
|
||||
verbose_name=_('To date'))
|
||||
position = models.ForeignKey(Position, on_delete=models.PROTECT,
|
||||
verbose_name=_('Position'))
|
||||
|
||||
objects = EstablishmentEmployeeQuerySet.as_manager()
|
||||
|
||||
|
||||
class Employee(BaseAttributes):
|
||||
"""Employee model."""
|
||||
|
||||
user = models.OneToOneField('account.User', on_delete=models.PROTECT,
|
||||
null=True, blank=True, default=None,
|
||||
verbose_name=_('User'))
|
||||
name = models.CharField(max_length=255, verbose_name=_('Last name'))
|
||||
establishments = models.ManyToManyField(Establishment, related_name='employees',
|
||||
through=EstablishmentEmployee)
|
||||
awards = generic.GenericRelation(to='main.Award')
|
||||
tags = generic.GenericRelation(to='main.MetaDataContent')
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
verbose_name = _('Employee')
|
||||
verbose_name_plural = _('Employees')
|
||||
|
||||
|
||||
class EstablishmentScheduleQuerySet(models.QuerySet):
|
||||
"""QuerySet for model EstablishmentSchedule"""
|
||||
|
|
@ -160,3 +255,124 @@ class EstablishmentSchedule(BaseAttributes):
|
|||
"""Meta class"""
|
||||
verbose_name = _('Establishment schedule')
|
||||
verbose_name_plural = _('Establishment schedules')
|
||||
|
||||
|
||||
class ContactPhone(models.Model):
|
||||
"""Contact phone model."""
|
||||
establishment = models.ForeignKey(
|
||||
Establishment, 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."""
|
||||
establishment = models.ForeignKey(
|
||||
Establishment, 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."""
|
||||
|
||||
name = TJSONField(
|
||||
blank=True, null=True, default=None, verbose_name=_('name'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
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.ForeignKey(
|
||||
'establishment.Menu', verbose_name=_('menu'), on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('plate')
|
||||
verbose_name_plural = _('plates')
|
||||
|
||||
def __str__(self):
|
||||
return f'plate_id:{self.id}'
|
||||
|
||||
|
||||
class Menu(TraslatedFieldsMixin, BaseAttributes):
|
||||
"""Menu model."""
|
||||
category = TJSONField(
|
||||
blank=True, null=True, default=None, verbose_name=_('category'),
|
||||
help_text='{"en-GB":"some text"}')
|
||||
establishment = models.ForeignKey(
|
||||
'establishment.Establishment', verbose_name=_('establishment'),
|
||||
on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _('menu')
|
||||
verbose_name_plural = _('menu')
|
||||
|
||||
|
||||
class CommentQuerySet(models.QuerySet):
|
||||
"""QuerySets for Comment model."""
|
||||
|
||||
def by_author(self, author):
|
||||
"""Return comments by author"""
|
||||
return self.filter(author=author)
|
||||
|
||||
|
||||
class Comment(ProjectBaseMixin):
|
||||
"""Comment model."""
|
||||
text = models.TextField(verbose_name=_('Comment text'))
|
||||
mark = models.PositiveIntegerField(blank=True, null=True,
|
||||
default=None,
|
||||
verbose_name=_('Mark'))
|
||||
author = models.ForeignKey('account.User',
|
||||
related_name='comments',
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_('Author'))
|
||||
establishment = models.ForeignKey(Establishment,
|
||||
related_name='comments',
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_('Establishment'))
|
||||
|
||||
objects = CommentQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
"""Meta class"""
|
||||
verbose_name = _('Comment')
|
||||
verbose_name_plural = _('Comments')
|
||||
|
||||
def __str__(self):
|
||||
"""String representation"""
|
||||
return str(self.author)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,57 @@
|
|||
"""Establishment serializers."""
|
||||
from rest_framework import serializers
|
||||
|
||||
from establishment import models
|
||||
from location.serializers import AddressSerializer
|
||||
from main.serializers import MetaDataContentSerializer, AwardSerializer
|
||||
from main.serializers import MetaDataContentSerializer, AwardSerializer, CurrencySerializer
|
||||
from review import models as review_models
|
||||
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 PlateSerializer(serializers.ModelSerializer):
|
||||
currency = CurrencySerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = models.Plate
|
||||
fields = [
|
||||
'name_translated',
|
||||
'currency',
|
||||
'price',
|
||||
'is_signature_plate',
|
||||
]
|
||||
|
||||
|
||||
class MenuSerializers(serializers.ModelSerializer):
|
||||
plates = PlateSerializer(read_only=True, many=True, source='plate_set')
|
||||
category_translated = serializers.CharField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = models.Menu
|
||||
fields = [
|
||||
'id',
|
||||
'category_translated',
|
||||
'plates'
|
||||
]
|
||||
|
||||
|
||||
class EstablishmentTypeSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for EstablishmentType model."""
|
||||
|
||||
|
|
@ -46,6 +92,50 @@ class EstablishmentScheduleSerializer(serializers.ModelSerializer):
|
|||
)
|
||||
|
||||
|
||||
class ReviewSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model Review."""
|
||||
text_translated = serializers.CharField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = review_models.Review
|
||||
fields = (
|
||||
'text_translated',
|
||||
)
|
||||
|
||||
|
||||
class CommentSerializer(serializers.ModelSerializer):
|
||||
"""Comment serializer"""
|
||||
nickname = serializers.CharField(source='author.username')
|
||||
profile_pic = serializers.ImageField(source='author.image')
|
||||
|
||||
class Meta:
|
||||
"""Serializer for model Comment"""
|
||||
model = models.Comment
|
||||
fields = (
|
||||
'created',
|
||||
'text',
|
||||
'mark',
|
||||
'nickname',
|
||||
'profile_pic'
|
||||
)
|
||||
|
||||
|
||||
class EstablishmentEmployeeSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for actual employees."""
|
||||
|
||||
id = serializers.IntegerField(source='employee.id')
|
||||
name = serializers.CharField(source='employee.name')
|
||||
position_translated = serializers.CharField(source='position.name_translated')
|
||||
awards = AwardSerializer(source='employee.awards', many=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
||||
model = models.Employee
|
||||
fields = ('id', 'name', 'position_translated', 'awards')
|
||||
|
||||
|
||||
class EstablishmentSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for Establishment model."""
|
||||
|
||||
|
|
@ -59,6 +149,17 @@ class EstablishmentSerializer(serializers.ModelSerializer):
|
|||
schedule = EstablishmentScheduleSerializer(source='schedule.schedule',
|
||||
many=True,
|
||||
allow_null=True)
|
||||
phones = ContactPhonesSerializer(read_only=True, many=True, )
|
||||
emails = ContactEmailsSerializer(read_only=True, many=True, )
|
||||
reviews = ReviewSerializer(source='reviews.last', allow_null=True)
|
||||
comments = CommentSerializer(many=True, allow_null=True)
|
||||
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
||||
many=True)
|
||||
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
||||
preview_image = serializers.SerializerMethodField()
|
||||
|
||||
best_price_menu = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
||||
best_price_carte = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
|
|
@ -75,8 +176,27 @@ class EstablishmentSerializer(serializers.ModelSerializer):
|
|||
'type',
|
||||
'subtypes',
|
||||
'image',
|
||||
'preview_image',
|
||||
'address',
|
||||
'tags',
|
||||
'awards',
|
||||
'schedule',
|
||||
'website',
|
||||
'facebook',
|
||||
'twitter',
|
||||
'lafourchette',
|
||||
'booking',
|
||||
'phones',
|
||||
'emails',
|
||||
'reviews',
|
||||
'comments',
|
||||
'employees',
|
||||
'menu',
|
||||
'best_price_menu',
|
||||
'best_price_carte'
|
||||
)
|
||||
|
||||
def get_preview_image(self, obj):
|
||||
"""Get preview image"""
|
||||
return obj.get_full_image_url(request=self.context.get('request'),
|
||||
thumbnail_key='establishment_preview')
|
||||
|
|
|
|||
|
|
@ -5,22 +5,32 @@ from utils.views import JWTGenericViewMixin
|
|||
from establishment import filters
|
||||
|
||||
|
||||
class EstablishmentListView(JWTGenericViewMixin, generics.ListAPIView):
|
||||
class EstablishmentMixin:
|
||||
"""Establishment mixin."""
|
||||
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = serializers.EstablishmentSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
"""Overrided method 'get_queryset'."""
|
||||
return models.Establishment.objects.all().prefetch_actual_employees()
|
||||
|
||||
|
||||
class EstablishmentListView(EstablishmentMixin, JWTGenericViewMixin, generics.ListAPIView):
|
||||
"""Resource for getting a list of establishments."""
|
||||
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = serializers.EstablishmentSerializer
|
||||
queryset = models.Establishment.objects.all()
|
||||
filter_class = filters.EstablishmentFilter
|
||||
|
||||
def get_queryset(self):
|
||||
"""Overrided method 'get_queryset'."""
|
||||
return models.Establishment.objects.all()\
|
||||
.prefetch_actual_employees()\
|
||||
.by_country_code(code=self.request.country_code)
|
||||
|
||||
class EstablishmentRetrieveView(JWTGenericViewMixin, generics.RetrieveAPIView):
|
||||
|
||||
class EstablishmentRetrieveView(EstablishmentMixin, JWTGenericViewMixin, generics.RetrieveAPIView):
|
||||
"""Resource for getting a establishment."""
|
||||
|
||||
permission_classes = (permissions.AllowAny,)
|
||||
serializer_class = serializers.EstablishmentSerializer
|
||||
queryset = models.Establishment.objects.all()
|
||||
|
||||
|
||||
class EstablishmentTypeListView(JWTGenericViewMixin, generics.ListAPIView):
|
||||
"""Resource for getting a list of establishment types."""
|
||||
|
|
|
|||
|
|
@ -30,6 +30,6 @@ class Migration(migrations.Migration):
|
|||
migrations.AddField(
|
||||
model_name='country',
|
||||
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'),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
19
apps/location/migrations/0009_auto_20190901_0831.py
Normal file
19
apps/location/migrations/0009_auto_20190901_0831.py
Normal 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'),
|
||||
),
|
||||
]
|
||||
|
|
@ -17,7 +17,7 @@ class Country(SVGImageMixin, ProjectBaseMixin):
|
|||
"""Country model."""
|
||||
|
||||
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'))
|
||||
low_price = models.IntegerField(default=25, verbose_name=_('Low price'))
|
||||
high_price = models.IntegerField(default=50, verbose_name=_('High price'))
|
||||
|
|
|
|||
|
|
@ -39,3 +39,10 @@ class MetaDataCategoryAdmin(admin.ModelAdmin):
|
|||
@admin.register(models.MetaDataContent)
|
||||
class MetaDataContentAdmin(admin.ModelAdmin):
|
||||
"""MetaDataContent admin"""
|
||||
|
||||
|
||||
@admin.register(models.Currency)
|
||||
class CurrencContentAdmin(admin.ModelAdmin):
|
||||
"""CurrencContent admin"""
|
||||
|
||||
|
||||
|
|
|
|||
35
apps/main/migrations/0013_auto_20190901_1032.py
Normal file
35
apps/main/migrations/0013_auto_20190901_1032.py
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 10:32
|
||||
|
||||
from django.db import migrations, models
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('main', '0012_auto_20190829_1155'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Currency',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=50, verbose_name='name')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'currency',
|
||||
'verbose_name_plural': 'currencies',
|
||||
},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='award',
|
||||
name='title',
|
||||
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='title'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='metadata',
|
||||
name='label',
|
||||
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='label'),
|
||||
),
|
||||
]
|
||||
|
|
@ -190,7 +190,7 @@ class Award(TraslatedFieldsMixin, models.Model):
|
|||
award_type = models.ForeignKey('main.AwardType', on_delete=models.CASCADE)
|
||||
title = TJSONField(
|
||||
_('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='')
|
||||
|
||||
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
|
||||
|
|
@ -228,7 +228,7 @@ class MetaData(TraslatedFieldsMixin, models.Model):
|
|||
"""MetaData model."""
|
||||
label = TJSONField(
|
||||
_('label'), null=True, blank=True,
|
||||
default=None, help_text='{"en":"some text"}')
|
||||
default=None, help_text='{"en-GB":"some text"}')
|
||||
category = models.ForeignKey(
|
||||
MetaDataCategory, verbose_name=_('category'), on_delete=models.CASCADE)
|
||||
|
||||
|
|
@ -250,3 +250,15 @@ class MetaDataContent(models.Model):
|
|||
object_id = models.PositiveIntegerField()
|
||||
content_object = generic.GenericForeignKey('content_type', 'object_id')
|
||||
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}'
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ class SiteSettingsSerializer(serializers.ModelSerializer):
|
|||
|
||||
class AwardSerializer(serializers.ModelSerializer):
|
||||
"""Award serializer."""
|
||||
|
||||
title_translated = serializers.CharField(read_only=True, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
|
|
@ -96,3 +97,13 @@ class MetaDataContentSerializer(serializers.ModelSerializer):
|
|||
'id',
|
||||
'label_translated',
|
||||
]
|
||||
|
||||
|
||||
class CurrencySerializer(serializers.ModelSerializer):
|
||||
"""Currency serializer"""
|
||||
class Meta:
|
||||
model = models.Currency
|
||||
fields = [
|
||||
'id',
|
||||
'name'
|
||||
]
|
||||
|
|
@ -22,7 +22,7 @@ class NewsListFilterSet(django_filters.FilterSet):
|
|||
"""Crappy search by title according to locale"""
|
||||
if value:
|
||||
locale = self.request.locale
|
||||
filters = {f'{name}__{locale}': value}
|
||||
filters = {f'{name}__{locale}__icontains': value}
|
||||
return queryset.filter(**filters)
|
||||
else:
|
||||
return queryset
|
||||
|
|
|
|||
29
apps/news/migrations/0009_auto_20190901_1032.py
Normal file
29
apps/news/migrations/0009_auto_20190901_1032.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 10:32
|
||||
|
||||
from django.db import migrations
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('news', '0008_auto_20190828_1522'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='news',
|
||||
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='news',
|
||||
name='subtitle',
|
||||
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='subtitle'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='news',
|
||||
name='title',
|
||||
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='title'),
|
||||
),
|
||||
]
|
||||
|
|
@ -43,14 +43,14 @@ class News(BaseAttributes, TraslatedFieldsMixin):
|
|||
|
||||
title = TJSONField(
|
||||
_('title'), null=True, blank=True,
|
||||
default=None, help_text='{"en":"some text"}')
|
||||
default=None, help_text='{"en-GB":"some text"}')
|
||||
subtitle = TJSONField(
|
||||
_('subtitle'), null=True, blank=True,
|
||||
default=None, help_text='{"en":"some text"}'
|
||||
default=None, help_text='{"en-GB":"some text"}'
|
||||
)
|
||||
description = TJSONField(
|
||||
_('description'), null=True, blank=True,
|
||||
default=None, help_text='{"en":"some text"}'
|
||||
default=None, help_text='{"en-GB":"some text"}'
|
||||
)
|
||||
start = models.DateTimeField(_('start'))
|
||||
end = models.DateTimeField(_('end'))
|
||||
|
|
|
|||
0
apps/review/__init__.py
Normal file
0
apps/review/__init__.py
Normal file
3
apps/review/admin.py
Normal file
3
apps/review/admin.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# @admin.register(models.Review)
|
||||
# class ReviewAdminModel(admin.ModelAdmin):
|
||||
# """Admin model for model Review."""
|
||||
7
apps/review/apps.py
Normal file
7
apps/review/apps.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
from django.apps import AppConfig
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class ReviewConfig(AppConfig):
|
||||
name = 'review'
|
||||
verbose_name = _('reviews')
|
||||
43
apps/review/migrations/0001_initial.py
Normal file
43
apps/review/migrations/0001_initial.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 09:32
|
||||
|
||||
import django.core.validators
|
||||
import django.utils.timezone
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('contenttypes', '0002_remove_content_type_name'),
|
||||
('translation', '0002_siteinterfacedictionary'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Review',
|
||||
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')),
|
||||
('object_id', models.PositiveIntegerField()),
|
||||
('text', models.TextField(verbose_name='Text')),
|
||||
('status', models.PositiveSmallIntegerField(choices=[(0, 'To investigate'), (1, 'To review'), (2, 'Ready')], default=0)),
|
||||
('published_at', models.DateTimeField(blank=True, default=None, help_text='Review published datetime', null=True, verbose_name='Publish datetime')),
|
||||
('vintage', models.IntegerField(validators=[django.core.validators.MinValueValidator(1900), django.core.validators.MaxValueValidator(2100)], verbose_name='Year of review')),
|
||||
('child', models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, to='review.Review', verbose_name='Child review')),
|
||||
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
|
||||
('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='review_records_created', to=settings.AUTH_USER_MODEL, verbose_name='created by')),
|
||||
('language', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reviews', to='translation.Language', verbose_name='Review language')),
|
||||
('modified_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='review_records_modified', to=settings.AUTH_USER_MODEL, verbose_name='modified by')),
|
||||
('reviewer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='reviews', to=settings.AUTH_USER_MODEL, verbose_name='Reviewer')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Review',
|
||||
'verbose_name_plural': 'Reviews',
|
||||
},
|
||||
),
|
||||
]
|
||||
17
apps/review/migrations/0002_remove_review_text.py
Normal file
17
apps/review/migrations/0002_remove_review_text.py
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 11:47
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('review', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='review',
|
||||
name='text',
|
||||
),
|
||||
]
|
||||
20
apps/review/migrations/0003_review_text.py
Normal file
20
apps/review/migrations/0003_review_text.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 11:53
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
import utils.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('review', '0002_remove_review_text'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='review',
|
||||
name='text',
|
||||
field=utils.models.TJSONField(blank=True, default=None, help_text='{"en-GB":"Text review"}', null=True, verbose_name='text'),
|
||||
),
|
||||
]
|
||||
0
apps/review/migrations/__init__.py
Normal file
0
apps/review/migrations/__init__.py
Normal file
64
apps/review/models.py
Normal file
64
apps/review/models.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
from django.contrib.contenttypes import fields as generic
|
||||
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from utils.models import BaseAttributes, TraslatedFieldsMixin
|
||||
from utils.models import TJSONField
|
||||
|
||||
|
||||
class ReviewQuerySet(models.QuerySet):
|
||||
"""QuerySets for model Review"""
|
||||
|
||||
def by_reviewer(self, user):
|
||||
"""Return reviews by user"""
|
||||
return self.filter(reviewer=user)
|
||||
|
||||
def by_vintage(self, year: int):
|
||||
"""Return reviews by year"""
|
||||
return self.filter(vintage=year)
|
||||
|
||||
|
||||
class Review(BaseAttributes, TraslatedFieldsMixin):
|
||||
"""Review model"""
|
||||
TO_INVESTIGATE = 0
|
||||
TO_REVIEW = 1
|
||||
READY = 2
|
||||
REVIEW_STATUSES = (
|
||||
(TO_INVESTIGATE, _('To investigate')),
|
||||
(TO_REVIEW, _('To review')),
|
||||
(READY, _('Ready')),
|
||||
)
|
||||
|
||||
reviewer = models.ForeignKey('account.User',
|
||||
related_name='reviews',
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_('Reviewer'))
|
||||
text = TJSONField(
|
||||
_('text'), null=True, blank=True,
|
||||
default=None, help_text='{"en-GB":"Text review"}')
|
||||
content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE)
|
||||
object_id = models.PositiveIntegerField()
|
||||
content_object = generic.GenericForeignKey('content_type', 'object_id')
|
||||
language = models.ForeignKey('translation.Language',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='reviews',
|
||||
verbose_name=_('Review language'))
|
||||
status = models.PositiveSmallIntegerField(choices=REVIEW_STATUSES, default=TO_INVESTIGATE)
|
||||
child = models.ForeignKey('self',
|
||||
blank=True, default=None, null=True,
|
||||
on_delete=models.CASCADE,
|
||||
verbose_name=_('Child review'))
|
||||
published_at = models.DateTimeField(verbose_name=_('Publish datetime'),
|
||||
blank=True, default=None, null=True,
|
||||
help_text=_('Review published datetime'))
|
||||
vintage = models.IntegerField(verbose_name=_('Year of review'),
|
||||
validators=[MinValueValidator(1900),
|
||||
MaxValueValidator(2100)])
|
||||
|
||||
objects = ReviewQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
verbose_name = _('Review')
|
||||
verbose_name_plural = _('Reviews')
|
||||
0
apps/review/serializers/__init__.py
Normal file
0
apps/review/serializers/__init__.py
Normal file
0
apps/review/serializers/common.py
Normal file
0
apps/review/serializers/common.py
Normal file
0
apps/review/serializers/mobile.py
Normal file
0
apps/review/serializers/mobile.py
Normal file
0
apps/review/serializers/web.py
Normal file
0
apps/review/serializers/web.py
Normal file
3
apps/review/tests.py
Normal file
3
apps/review/tests.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
||||
0
apps/review/urls/__init__.py
Normal file
0
apps/review/urls/__init__.py
Normal file
0
apps/review/urls/common.py
Normal file
0
apps/review/urls/common.py
Normal file
0
apps/review/urls/mobile.py
Normal file
0
apps/review/urls/mobile.py
Normal file
0
apps/review/urls/web.py
Normal file
0
apps/review/urls/web.py
Normal file
0
apps/review/views/__init__.py
Normal file
0
apps/review/views/__init__.py
Normal file
0
apps/review/views/common.py
Normal file
0
apps/review/views/common.py
Normal file
0
apps/review/views/mobile.py
Normal file
0
apps/review/views/mobile.py
Normal file
0
apps/review/views/web.py
Normal file
0
apps/review/views/web.py
Normal file
19
apps/translation/migrations/0003_auto_20190901_1032.py
Normal file
19
apps/translation/migrations/0003_auto_20190901_1032.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.2.4 on 2019-09-01 10:32
|
||||
|
||||
import django.contrib.postgres.fields.jsonb
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('translation', '0002_siteinterfacedictionary'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='siteinterfacedictionary',
|
||||
name='text',
|
||||
field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=None, help_text='{"en-GB":"some text"}', null=True, verbose_name='Text'),
|
||||
),
|
||||
]
|
||||
|
|
@ -49,7 +49,7 @@ class SiteInterfaceDictionary(ProjectBaseMixin):
|
|||
verbose_name=_('Page'))
|
||||
keywords = models.CharField(max_length=255, verbose_name='Keywords')
|
||||
text = JSONField(_('Text'), null=True, blank=True,
|
||||
default=None, help_text='{"en":"some text"}')
|
||||
default=None, help_text='{"en-GB":"some text"}')
|
||||
|
||||
objects = SiteInterfaceDictionaryManager()
|
||||
|
||||
|
|
|
|||
|
|
@ -74,9 +74,6 @@ class OAuthProjectMixin:
|
|||
return NotImplemented
|
||||
|
||||
|
||||
basemixin_fields = ['created', 'modified']
|
||||
|
||||
|
||||
class BaseAttributes(ProjectBaseMixin):
|
||||
created_by = models.ForeignKey(
|
||||
'account.User', on_delete=models.SET_NULL, verbose_name=_('created by'),
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ PROJECT_APPS = [
|
|||
'translation.apps.TranslationConfig',
|
||||
'configuration.apps.ConfigurationConfig',
|
||||
'timetable.apps.TimetableConfig',
|
||||
'review.apps.ReviewConfig',
|
||||
]
|
||||
|
||||
EXTERNAL_APPS = [
|
||||
|
|
@ -82,6 +83,7 @@ EXTERNAL_APPS = [
|
|||
'django_extensions',
|
||||
'rest_framework_simplejwt.token_blacklist',
|
||||
'solo',
|
||||
'phonenumber_field',
|
||||
]
|
||||
|
||||
|
||||
|
|
@ -321,6 +323,7 @@ THUMBNAIL_ALIASES = {
|
|||
'large': {'size': (1500, 0), },
|
||||
'default': {'size': (300, 200), 'crop': True},
|
||||
'gallery': {'size': (240, 160), 'crop': True},
|
||||
'establishment_preview': {'size': (300, 280), 'crop': True},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ djangorestframework-xml
|
|||
celery
|
||||
amqp>=2.4.0
|
||||
geoip2==2.9.0
|
||||
django-phonenumber-field[phonenumbers]==2.1.0
|
||||
|
||||
# auth socials
|
||||
djangorestframework-oauth
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user