Merge branch 'develop' into feature/add_tag_product
This commit is contained in:
commit
097bab4bb1
|
|
@ -6,4 +6,4 @@ from . import models
|
||||||
@admin.register(models.Comment)
|
@admin.register(models.Comment)
|
||||||
class CommentModelAdmin(admin.ModelAdmin):
|
class CommentModelAdmin(admin.ModelAdmin):
|
||||||
"""Model admin for model Comment"""
|
"""Model admin for model Comment"""
|
||||||
raw_id_fields = ('user', 'country')
|
raw_id_fields = ('user',)
|
||||||
|
|
|
||||||
17
apps/comment/migrations/0005_remove_comment_country.py
Normal file
17
apps/comment/migrations/0005_remove_comment_country.py
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Generated by Django 2.2.7 on 2019-11-12 13:17
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('comment', '0004_comment_old_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='comment',
|
||||||
|
name='country',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -4,10 +4,9 @@ from django.db import models
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from account.models import User
|
from account.models import User
|
||||||
|
from translation.models import Language
|
||||||
from utils.models import ProjectBaseMixin
|
from utils.models import ProjectBaseMixin
|
||||||
from utils.querysets import ContentTypeQuerySetMixin
|
from utils.querysets import ContentTypeQuerySetMixin
|
||||||
from translation.models import Language
|
|
||||||
from location.models import Country
|
|
||||||
|
|
||||||
|
|
||||||
class CommentQuerySet(ContentTypeQuerySetMixin):
|
class CommentQuerySet(ContentTypeQuerySetMixin):
|
||||||
|
|
@ -34,7 +33,6 @@ class Comment(ProjectBaseMixin):
|
||||||
text = models.TextField(verbose_name=_('Comment text'))
|
text = models.TextField(verbose_name=_('Comment text'))
|
||||||
mark = models.PositiveIntegerField(blank=True, null=True, default=None, verbose_name=_('Mark'))
|
mark = models.PositiveIntegerField(blank=True, null=True, default=None, verbose_name=_('Mark'))
|
||||||
user = models.ForeignKey('account.User', related_name='comments', on_delete=models.CASCADE, verbose_name=_('User'))
|
user = models.ForeignKey('account.User', related_name='comments', on_delete=models.CASCADE, verbose_name=_('User'))
|
||||||
country = models.ForeignKey(Country, verbose_name=_('Country'), on_delete=models.SET_NULL, null=True)
|
|
||||||
old_id = models.IntegerField(null=True, blank=True, default=None)
|
old_id = models.IntegerField(null=True, blank=True, default=None)
|
||||||
|
|
||||||
content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE)
|
content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE)
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
from django.db.models import Q
|
from account.models import User
|
||||||
|
from establishment.models import Establishment
|
||||||
from account.transfer_data import STOP_LIST
|
|
||||||
from transfer.models import Comments
|
from transfer.models import Comments
|
||||||
from transfer.serializers.comments import CommentSerializer
|
from transfer.serializers.comments import CommentSerializer
|
||||||
|
|
||||||
|
|
@ -10,19 +9,15 @@ from transfer.serializers.comments import CommentSerializer
|
||||||
def transfer_comments():
|
def transfer_comments():
|
||||||
# В queryset исключены объекты по условию в связанные моделях
|
# В queryset исключены объекты по условию в связанные моделях
|
||||||
# см. transfer_establishment() и transfer_user()
|
# см. transfer_establishment() и transfer_user()
|
||||||
queryset = Comments.objects.exclude(
|
establishments = Establishment.objects.all().values_list('old_id', flat=True)
|
||||||
Q(establishment__type='Wineyard') |
|
users = User.objects.all().values_list('old_id', flat=True)
|
||||||
Q(establishment__location__timezone__isnull=True) |
|
queryset = Comments.objects.filter(
|
||||||
Q(account__confirmed_at__isnull=True) |
|
establishment_id__in=list(establishments),
|
||||||
Q(account__email__in=STOP_LIST)
|
account_id__in=list(users),
|
||||||
).filter(
|
|
||||||
account__isnull=False,
|
|
||||||
mark__isnull=False
|
|
||||||
).only(
|
).only(
|
||||||
'id',
|
'id',
|
||||||
'comment',
|
'comment',
|
||||||
'mark',
|
'mark',
|
||||||
'locale',
|
|
||||||
'establishment_id',
|
'establishment_id',
|
||||||
'account_id',
|
'account_id',
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from timetable.models import Timetable
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = '''Add closed_at, opening_at Timetable fields'''
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
for tt in Timetable.objects.all():
|
||||||
|
end = tt.dinner_end or tt.lunch_end
|
||||||
|
start = tt.lunch_start or tt.dinner_start
|
||||||
|
if end or start:
|
||||||
|
tt.closed_at = end
|
||||||
|
tt.opening_at = start
|
||||||
|
tt.save()
|
||||||
33
apps/establishment/migrations/0059_establishmentnote.py
Normal file
33
apps/establishment/migrations/0059_establishmentnote.py
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
# Generated by Django 2.2.7 on 2019-11-12 10:07
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('establishment', '0058_merge_20191106_0921'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EstablishmentNote',
|
||||||
|
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')),
|
||||||
|
('old_id', models.PositiveIntegerField(blank=True, null=True)),
|
||||||
|
('text', models.TextField(verbose_name='text')),
|
||||||
|
('establishment', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='establishment_notes', to='establishment.Establishment', verbose_name='establishment')),
|
||||||
|
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='establishment_notes', to=settings.AUTH_USER_MODEL, verbose_name='author')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'product notes',
|
||||||
|
'verbose_name_plural': 'product note',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -111,6 +111,19 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
return self.select_related('address', 'establishment_type').\
|
return self.select_related('address', 'establishment_type').\
|
||||||
prefetch_related('tags')
|
prefetch_related('tags')
|
||||||
|
|
||||||
|
def with_schedule(self):
|
||||||
|
"""Return qs with related schedule."""
|
||||||
|
return self.prefetch_related('schedule')
|
||||||
|
|
||||||
|
def with_currency_related(self):
|
||||||
|
"""Return qs with related """
|
||||||
|
return self.prefetch_related('currency')
|
||||||
|
|
||||||
|
def with_extended_address_related(self):
|
||||||
|
"""Return qs with deeply related address models."""
|
||||||
|
return self.select_related('address__city', 'address__city__region', 'address__city__region__country',
|
||||||
|
'address__city__country')
|
||||||
|
|
||||||
def with_extended_related(self):
|
def with_extended_related(self):
|
||||||
return self.select_related('establishment_type').\
|
return self.select_related('establishment_type').\
|
||||||
prefetch_related('establishment_subtypes', 'awards', 'schedule',
|
prefetch_related('establishment_subtypes', 'awards', 'schedule',
|
||||||
|
|
@ -461,6 +474,11 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
||||||
""" Used for indexing working by day """
|
""" Used for indexing working by day """
|
||||||
return [ret.weekday for ret in self.schedule.all() if ret.works_at_noon]
|
return [ret.weekday for ret in self.schedule.all() if ret.works_at_noon]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def works_at_weekday(self):
|
||||||
|
""" Used for indexing by working whole day criteria """
|
||||||
|
return [ret.weekday for ret in self.schedule.all()]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def works_evening(self):
|
def works_evening(self):
|
||||||
""" Used for indexing working by day """
|
""" Used for indexing working by day """
|
||||||
|
|
@ -520,6 +538,30 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
|
||||||
return self.products.wines()
|
return self.products.wines()
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentNoteQuerySet(models.QuerySet):
|
||||||
|
"""QuerySet for model EstablishmentNote."""
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentNote(ProjectBaseMixin):
|
||||||
|
"""Note model for Establishment entity."""
|
||||||
|
old_id = models.PositiveIntegerField(null=True, blank=True)
|
||||||
|
text = models.TextField(verbose_name=_('text'))
|
||||||
|
establishment = models.ForeignKey(Establishment, on_delete=models.PROTECT,
|
||||||
|
related_name='establishment_notes',
|
||||||
|
verbose_name=_('establishment'))
|
||||||
|
user = models.ForeignKey('account.User', on_delete=models.PROTECT,
|
||||||
|
null=True,
|
||||||
|
related_name='establishment_notes',
|
||||||
|
verbose_name=_('author'))
|
||||||
|
|
||||||
|
objects = EstablishmentNoteQuerySet.as_manager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
verbose_name_plural = _('product note')
|
||||||
|
verbose_name = _('product notes')
|
||||||
|
|
||||||
|
|
||||||
class Position(BaseAttributes, TranslatedFieldsMixin):
|
class Position(BaseAttributes, TranslatedFieldsMixin):
|
||||||
"""Position model."""
|
"""Position model."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ from rest_framework import serializers
|
||||||
from comment import models as comment_models
|
from comment import models as comment_models
|
||||||
from comment.serializers import common as comment_serializers
|
from comment.serializers import common as comment_serializers
|
||||||
from establishment import models
|
from establishment import models
|
||||||
from location.serializers import AddressBaseSerializer, CitySerializer
|
from location.serializers import AddressBaseSerializer, CitySerializer, AddressDetailSerializer
|
||||||
from main.serializers import AwardSerializer, CurrencySerializer
|
from main.serializers import AwardSerializer, CurrencySerializer
|
||||||
from tag.serializers import TagBaseSerializer
|
from tag.serializers import TagBaseSerializer
|
||||||
from timetable.serialziers import ScheduleRUDSerializer
|
from timetable.serialziers import ScheduleRUDSerializer
|
||||||
|
|
@ -225,6 +225,19 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
|
||||||
'currency'
|
'currency'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class EstablishmentListRetrieveSerializer(EstablishmentBaseSerializer):
|
||||||
|
"""Establishment with city serializer."""
|
||||||
|
|
||||||
|
address = AddressDetailSerializer()
|
||||||
|
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
||||||
|
|
||||||
|
class Meta(EstablishmentBaseSerializer.Meta):
|
||||||
|
"""Meta class."""
|
||||||
|
|
||||||
|
fields = EstablishmentBaseSerializer.Meta.fields + [
|
||||||
|
'schedule',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentGeoSerializer(EstablishmentBaseSerializer):
|
class EstablishmentGeoSerializer(EstablishmentBaseSerializer):
|
||||||
"""Serializer for Geo view."""
|
"""Serializer for Geo view."""
|
||||||
|
|
@ -260,6 +273,8 @@ class EstablishmentDetailSerializer(EstablishmentBaseSerializer):
|
||||||
review = ReviewShortSerializer(source='last_published_review', allow_null=True)
|
review = ReviewShortSerializer(source='last_published_review', allow_null=True)
|
||||||
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
employees = EstablishmentEmployeeSerializer(source='actual_establishment_employees',
|
||||||
many=True)
|
many=True)
|
||||||
|
address = AddressDetailSerializer(read_only=True)
|
||||||
|
|
||||||
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
menu = MenuSerializers(source='menu_set', many=True, read_only=True)
|
||||||
best_price_menu = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
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)
|
best_price_carte = serializers.DecimalField(max_digits=14, decimal_places=2, read_only=True)
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,9 @@ from django.db.models import Q, F
|
||||||
|
|
||||||
from establishment.models import Establishment
|
from establishment.models import Establishment
|
||||||
from location.models import Address
|
from location.models import Address
|
||||||
from transfer.models import Establishments, Dishes
|
from transfer.models import Establishments, Dishes, EstablishmentNotes
|
||||||
from transfer.serializers.establishment import EstablishmentSerializer
|
from transfer.serializers.establishment import EstablishmentSerializer, \
|
||||||
|
EstablishmentNoteSerializer
|
||||||
from transfer.serializers.plate import PlateSerializer
|
from transfer.serializers.plate import PlateSerializer
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -124,10 +125,26 @@ def transfer_establishment_addresses():
|
||||||
establishment.save()
|
establishment.save()
|
||||||
|
|
||||||
|
|
||||||
|
def transfer_establishment_note():
|
||||||
|
errors = []
|
||||||
|
queryset = EstablishmentNotes.objects.exclude(text__exact='') \
|
||||||
|
.exclude(text__isnull=True) \
|
||||||
|
.exclude(establishment_id__isnull=True)
|
||||||
|
serialized_data = EstablishmentNoteSerializer(
|
||||||
|
data=list(queryset.values()),
|
||||||
|
many=True)
|
||||||
|
if serialized_data.is_valid():
|
||||||
|
serialized_data.save()
|
||||||
|
else:
|
||||||
|
for d in serialized_data.errors: errors.append(d) if d else None
|
||||||
|
pprint(f"transfer_establishment_note errors: {errors}")
|
||||||
|
|
||||||
|
|
||||||
data_types = {
|
data_types = {
|
||||||
"establishment": [
|
"establishment": [
|
||||||
transfer_establishment,
|
transfer_establishment,
|
||||||
],
|
],
|
||||||
|
"establishment_note": [transfer_establishment_note],
|
||||||
"location_establishment": [
|
"location_establishment": [
|
||||||
transfer_establishment_addresses
|
transfer_establishment_addresses
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,11 @@ class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView):
|
||||||
"""Resource for getting a list of establishments."""
|
"""Resource for getting a list of establishments."""
|
||||||
|
|
||||||
filter_class = filters.EstablishmentFilter
|
filter_class = filters.EstablishmentFilter
|
||||||
serializer_class = serializers.EstablishmentBaseSerializer
|
serializer_class = serializers.EstablishmentListRetrieveSerializer
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return super().get_queryset().with_schedule()\
|
||||||
|
.with_extended_address_related().with_currency_related()
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class CitySerializer(serializers.ModelSerializer):
|
||||||
queryset=models.Country.objects.all(),
|
queryset=models.Country.objects.all(),
|
||||||
write_only=True
|
write_only=True
|
||||||
)
|
)
|
||||||
country = CountrySerializer()
|
country = CountrySerializer(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.City
|
model = models.City
|
||||||
|
|
|
||||||
18
apps/main/migrations/0034_sitefeature_nested.py
Normal file
18
apps/main/migrations/0034_sitefeature_nested.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 2.2.4 on 2019-11-07 14:41
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('main', '0033_auto_20191106_0744'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='sitefeature',
|
||||||
|
name='nested',
|
||||||
|
field=models.ManyToManyField(to='main.SiteFeature'),
|
||||||
|
),
|
||||||
|
]
|
||||||
14
apps/main/migrations/0035_merge_20191112_1218.py
Normal file
14
apps/main/migrations/0035_merge_20191112_1218.py
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Generated by Django 2.2.7 on 2019-11-12 12:18
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('main', '0034_sitefeature_nested'),
|
||||||
|
('main', '0034_auto_20191112_0104'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
]
|
||||||
|
|
@ -151,6 +151,7 @@ class SiteFeature(ProjectBaseMixin):
|
||||||
feature = models.ForeignKey(Feature, on_delete=models.PROTECT)
|
feature = models.ForeignKey(Feature, on_delete=models.PROTECT)
|
||||||
published = models.BooleanField(default=False, verbose_name=_('Published'))
|
published = models.BooleanField(default=False, verbose_name=_('Published'))
|
||||||
main = models.BooleanField(default=False, verbose_name=_('Main'))
|
main = models.BooleanField(default=False, verbose_name=_('Main'))
|
||||||
|
nested = models.ManyToManyField('self', symmetrical=False)
|
||||||
|
|
||||||
objects = SiteFeatureQuerySet.as_manager()
|
objects = SiteFeatureQuerySet.as_manager()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from rest_framework import serializers
|
||||||
from advertisement.serializers.web import AdvertisementSerializer
|
from advertisement.serializers.web import AdvertisementSerializer
|
||||||
from location.serializers import CountrySerializer
|
from location.serializers import CountrySerializer
|
||||||
from main import models
|
from main import models
|
||||||
from utils.serializers import ProjectModelSerializer, TranslatedField
|
from utils.serializers import ProjectModelSerializer, TranslatedField, RecursiveFieldSerializer
|
||||||
|
|
||||||
|
|
||||||
class FeatureSerializer(serializers.ModelSerializer):
|
class FeatureSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -27,6 +27,7 @@ class SiteFeatureSerializer(serializers.ModelSerializer):
|
||||||
priority = serializers.IntegerField(source='feature.priority')
|
priority = serializers.IntegerField(source='feature.priority')
|
||||||
route = serializers.CharField(source='feature.route.page_name')
|
route = serializers.CharField(source='feature.route.page_name')
|
||||||
source = serializers.IntegerField(source='feature.source')
|
source = serializers.IntegerField(source='feature.source')
|
||||||
|
nested = RecursiveFieldSerializer(many=True, allow_null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
@ -36,8 +37,9 @@ class SiteFeatureSerializer(serializers.ModelSerializer):
|
||||||
'slug',
|
'slug',
|
||||||
'priority',
|
'priority',
|
||||||
'route',
|
'route',
|
||||||
'source'
|
'source',
|
||||||
)
|
'nested',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class CurrencySerializer(ProjectModelSerializer):
|
class CurrencySerializer(ProjectModelSerializer):
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,21 @@
|
||||||
"""Filters from application News"""
|
"""Filters from application News"""
|
||||||
import django_filters
|
from django_filters import rest_framework as filters
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from news import models
|
from news import models
|
||||||
|
|
||||||
|
|
||||||
class NewsListFilterSet(django_filters.FilterSet):
|
class NewsListFilterSet(filters.FilterSet):
|
||||||
"""FilterSet for News list"""
|
"""FilterSet for News list"""
|
||||||
|
|
||||||
is_highlighted = django_filters.BooleanFilter()
|
is_highlighted = filters.BooleanFilter()
|
||||||
title = django_filters.CharFilter(method='by_title')
|
title = filters.CharFilter(method='by_title')
|
||||||
|
tag_group = filters.ChoiceFilter(
|
||||||
|
choices=(
|
||||||
|
(models.News.RECIPES_TAG_VALUE, _('Recipes')),
|
||||||
|
),
|
||||||
|
method='by_tag_group'
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class"""
|
"""Meta class"""
|
||||||
|
|
@ -16,8 +23,14 @@ class NewsListFilterSet(django_filters.FilterSet):
|
||||||
fields = (
|
fields = (
|
||||||
'title',
|
'title',
|
||||||
'is_highlighted',
|
'is_highlighted',
|
||||||
|
'tag_group',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def by_tag_group(self, queryset, name, value):
|
||||||
|
if value == models.News.RECIPES_TAG_VALUE:
|
||||||
|
queryset = queryset.recipe_news()
|
||||||
|
return queryset
|
||||||
|
|
||||||
def by_title(self, queryset, name, value):
|
def by_title(self, queryset, name, value):
|
||||||
"""Crappy search by title according to locale"""
|
"""Crappy search by title according to locale"""
|
||||||
if value:
|
if value:
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,10 @@ class NewsQuerySet(TranslationQuerysetMixin):
|
||||||
"""Filter collection by country code."""
|
"""Filter collection by country code."""
|
||||||
return self.filter(country__code=code)
|
return self.filter(country__code=code)
|
||||||
|
|
||||||
|
def recipe_news(self):
|
||||||
|
"""Returns news with tag 'cook' qs."""
|
||||||
|
return self.filter(tags__value=News.RECIPES_TAG_VALUE)
|
||||||
|
|
||||||
def published(self):
|
def published(self):
|
||||||
"""Return only published news"""
|
"""Return only published news"""
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
|
|
@ -127,6 +131,8 @@ class News(BaseAttributes, TranslatedFieldsMixin):
|
||||||
(PUBLISHED_EXCLUSIVE, _('Published exclusive')),
|
(PUBLISHED_EXCLUSIVE, _('Published exclusive')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
RECIPES_TAG_VALUE = 'cook'
|
||||||
|
|
||||||
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
|
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
|
||||||
news_type = models.ForeignKey(NewsType, on_delete=models.PROTECT,
|
news_type = models.ForeignKey(NewsType, on_delete=models.PROTECT,
|
||||||
verbose_name=_('news type'))
|
verbose_name=_('news type'))
|
||||||
|
|
|
||||||
9
apps/news/urls/common.py
Normal file
9
apps/news/urls/common.py
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
from django.urls import path
|
||||||
|
from news import views
|
||||||
|
|
||||||
|
common_urlpatterns = [
|
||||||
|
path('', views.NewsListView.as_view(), name='list'),
|
||||||
|
path('types/', views.NewsTypeListView.as_view(), name='type'),
|
||||||
|
path('slug/<slug:slug>/', views.NewsDetailView.as_view(), name='rud'),
|
||||||
|
path('slug/<slug:slug>/favorites/', views.NewsFavoritesCreateDestroyView.as_view(), name='create-destroy-favorites')
|
||||||
|
]
|
||||||
8
apps/news/urls/mobile.py
Normal file
8
apps/news/urls/mobile.py
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
"""News app urlconf."""
|
||||||
|
from news.urls.common import common_urlpatterns
|
||||||
|
|
||||||
|
app_name = 'news'
|
||||||
|
|
||||||
|
urlpatterns = []
|
||||||
|
|
||||||
|
urlpatterns.extend(common_urlpatterns)
|
||||||
|
|
@ -1,12 +1,8 @@
|
||||||
"""News app urlconf."""
|
"""News app urlconf."""
|
||||||
from django.urls import path
|
from news.urls.common import common_urlpatterns
|
||||||
from news import views
|
|
||||||
|
|
||||||
app_name = 'news'
|
app_name = 'news'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = []
|
||||||
path('', views.NewsListView.as_view(), name='list'),
|
|
||||||
path('types/', views.NewsTypeListView.as_view(), name='type'),
|
urlpatterns.extend(common_urlpatterns)
|
||||||
path('slug/<slug:slug>/', views.NewsDetailView.as_view(), name='rud'),
|
|
||||||
path('slug/<slug:slug>/favorites/', views.NewsFavoritesCreateDestroyView.as_view(), name='create-destroy-favorites')
|
|
||||||
]
|
|
||||||
|
|
|
||||||
37
apps/product/migrations/0012_auto_20191112_1007.py
Normal file
37
apps/product/migrations/0012_auto_20191112_1007.py
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Generated by Django 2.2.7 on 2019-11-12 10:07
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('product', '0011_product_win_import_id'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='product',
|
||||||
|
name='win_import_id',
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ProductNote',
|
||||||
|
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')),
|
||||||
|
('old_id', models.PositiveIntegerField(blank=True, null=True)),
|
||||||
|
('text', models.TextField(verbose_name='text')),
|
||||||
|
('product', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='product_notes', to='product.Product', verbose_name='product')),
|
||||||
|
('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='product_notes', to=settings.AUTH_USER_MODEL, verbose_name='author')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'product notes',
|
||||||
|
'verbose_name_plural': 'product note',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -193,9 +193,6 @@ class Product(TranslatedFieldsMixin, BaseAttributes):
|
||||||
validators=[MinValueValidator(EARLIEST_VINTAGE_YEAR),
|
validators=[MinValueValidator(EARLIEST_VINTAGE_YEAR),
|
||||||
MaxValueValidator(LATEST_VINTAGE_YEAR)])
|
MaxValueValidator(LATEST_VINTAGE_YEAR)])
|
||||||
gallery = models.ManyToManyField('gallery.Image', through='ProductGallery')
|
gallery = models.ManyToManyField('gallery.Image', through='ProductGallery')
|
||||||
win_import_id = models.CharField(max_length=255,
|
|
||||||
blank=True, null=True, default=None,
|
|
||||||
help_text=_('attribute from legacy db'))
|
|
||||||
reviews = generic.GenericRelation(to='review.Review')
|
reviews = generic.GenericRelation(to='review.Review')
|
||||||
comments = generic.GenericRelation(to='comment.Comment')
|
comments = generic.GenericRelation(to='comment.Comment')
|
||||||
awards = generic.GenericRelation(to='main.Award', related_query_name='product')
|
awards = generic.GenericRelation(to='main.Award', related_query_name='product')
|
||||||
|
|
@ -409,3 +406,27 @@ class ProductClassification(models.Model):
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
verbose_name = _('product classification')
|
verbose_name = _('product classification')
|
||||||
verbose_name_plural = _('product classifications')
|
verbose_name_plural = _('product classifications')
|
||||||
|
|
||||||
|
|
||||||
|
class ProductNoteQuerySet(models.QuerySet):
|
||||||
|
"""QuerySet for model ProductNote."""
|
||||||
|
|
||||||
|
|
||||||
|
class ProductNote(ProjectBaseMixin):
|
||||||
|
"""Note model for Product entity."""
|
||||||
|
old_id = models.PositiveIntegerField(null=True, blank=True)
|
||||||
|
text = models.TextField(verbose_name=_('text'))
|
||||||
|
product = models.ForeignKey(Product, on_delete=models.PROTECT,
|
||||||
|
related_name='product_notes',
|
||||||
|
verbose_name=_('product'))
|
||||||
|
user = models.ForeignKey('account.User', on_delete=models.PROTECT,
|
||||||
|
null=True,
|
||||||
|
related_name='product_notes',
|
||||||
|
verbose_name=_('author'))
|
||||||
|
|
||||||
|
objects = ProductNoteQuerySet.as_manager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
verbose_name_plural = _('product note')
|
||||||
|
verbose_name = _('product notes')
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class ProductBaseSerializer(serializers.ModelSerializer):
|
||||||
subtypes = ProductSubTypeBaseSerializer(many=True)
|
subtypes = ProductSubTypeBaseSerializer(many=True)
|
||||||
establishment = EstablishmentShortSerializer()
|
establishment = EstablishmentShortSerializer()
|
||||||
tags = TagBaseSerializer(source='related_tags', many=True)
|
tags = TagBaseSerializer(source='related_tags', many=True)
|
||||||
preview_image_url = serializers.ImageField(source='preview_main_image_url', allow_null=True)
|
preview_image_url = serializers.URLField(source='preview_main_image_url', allow_null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ def transfer_wine_classifications():
|
||||||
|
|
||||||
|
|
||||||
def transfer_product():
|
def transfer_product():
|
||||||
|
errors = []
|
||||||
queryset = transfer_models.Products.objects.all()
|
queryset = transfer_models.Products.objects.all()
|
||||||
serialized_data = product_serializers.ProductSerializer(
|
serialized_data = product_serializers.ProductSerializer(
|
||||||
data=list(queryset.values()),
|
data=list(queryset.values()),
|
||||||
|
|
@ -108,26 +109,25 @@ def transfer_product():
|
||||||
if serialized_data.is_valid():
|
if serialized_data.is_valid():
|
||||||
serialized_data.save()
|
serialized_data.save()
|
||||||
else:
|
else:
|
||||||
errors = []
|
|
||||||
for d in serialized_data.errors: errors.append(d) if d else None
|
for d in serialized_data.errors: errors.append(d) if d else None
|
||||||
pprint(f"transfer_product errors: {errors}")
|
pprint(f"transfer_product errors: {errors}")
|
||||||
|
|
||||||
|
|
||||||
def transfer_product_description():
|
def transfer_product_note():
|
||||||
pass
|
errors = []
|
||||||
# queryset = transfer_models.Products.objects.all()
|
queryset = transfer_models.ProductNotes.objects.exclude(text='')
|
||||||
# serialized_data = product_serializers.ProductSerializer(
|
serialized_data = product_serializers.ProductNoteSerializer(
|
||||||
# data=list(queryset.values()),
|
data=list(queryset.values()),
|
||||||
# many=True)
|
many=True)
|
||||||
# if serialized_data.is_valid():
|
if serialized_data.is_valid():
|
||||||
# serialized_data.save()
|
serialized_data.save()
|
||||||
# else:
|
else:
|
||||||
# errors = []
|
for d in serialized_data.errors: errors.append(d) if d else None
|
||||||
# for d in serialized_data.errors: errors.append(d) if d else None
|
pprint(f"transfer_product_note errors: {errors}")
|
||||||
# pprint(f"transfer_product errors: {errors}")
|
|
||||||
|
|
||||||
|
|
||||||
def transfer_plate():
|
def transfer_plate():
|
||||||
|
errors = []
|
||||||
queryset = transfer_models.Merchandise.objects.all()
|
queryset = transfer_models.Merchandise.objects.all()
|
||||||
serialized_data = product_serializers.PlateSerializer(
|
serialized_data = product_serializers.PlateSerializer(
|
||||||
data=list(queryset.values()),
|
data=list(queryset.values()),
|
||||||
|
|
@ -135,12 +135,12 @@ def transfer_plate():
|
||||||
if serialized_data.is_valid():
|
if serialized_data.is_valid():
|
||||||
serialized_data.save()
|
serialized_data.save()
|
||||||
else:
|
else:
|
||||||
errors = []
|
|
||||||
for d in serialized_data.errors: errors.append(d) if d else None
|
for d in serialized_data.errors: errors.append(d) if d else None
|
||||||
pprint(f"transfer_plates errors: {errors}")
|
pprint(f"transfer_plates errors: {errors}")
|
||||||
|
|
||||||
|
|
||||||
def transfer_plate_image():
|
def transfer_plate_image():
|
||||||
|
errors = []
|
||||||
queryset = transfer_models.Merchandise.objects.all()
|
queryset = transfer_models.Merchandise.objects.all()
|
||||||
serialized_data = product_serializers.PlateImageSerializer(
|
serialized_data = product_serializers.PlateImageSerializer(
|
||||||
data=list(queryset.values()),
|
data=list(queryset.values()),
|
||||||
|
|
@ -148,7 +148,6 @@ def transfer_plate_image():
|
||||||
if serialized_data.is_valid():
|
if serialized_data.is_valid():
|
||||||
serialized_data.save()
|
serialized_data.save()
|
||||||
else:
|
else:
|
||||||
errors = []
|
|
||||||
for d in serialized_data.errors: errors.append(d) if d else None
|
for d in serialized_data.errors: errors.append(d) if d else None
|
||||||
pprint(f"transfer_plates_images errors: {errors}")
|
pprint(f"transfer_plates_images errors: {errors}")
|
||||||
|
|
||||||
|
|
@ -166,9 +165,9 @@ data_types = {
|
||||||
"product": [
|
"product": [
|
||||||
transfer_product,
|
transfer_product,
|
||||||
],
|
],
|
||||||
# "product_description": [
|
"product_note": [
|
||||||
# transfer_product_description,
|
transfer_product_note,
|
||||||
# ],
|
],
|
||||||
"souvenir": [
|
"souvenir": [
|
||||||
transfer_plate,
|
transfer_plate,
|
||||||
transfer_plate_image,
|
transfer_plate_image,
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@ class EstablishmentDocument(Document):
|
||||||
works_noon = fields.ListField(fields.IntegerField(
|
works_noon = fields.ListField(fields.IntegerField(
|
||||||
attr='works_noon'
|
attr='works_noon'
|
||||||
))
|
))
|
||||||
|
works_at_weekday = fields.ListField(fields.IntegerField(
|
||||||
|
attr='works_at_weekday'
|
||||||
|
))
|
||||||
works_now = fields.BooleanField(attr='works_now')
|
works_now = fields.BooleanField(attr='works_now')
|
||||||
tags = fields.ObjectField(
|
tags = fields.ObjectField(
|
||||||
properties={
|
properties={
|
||||||
|
|
@ -65,7 +68,6 @@ class EstablishmentDocument(Document):
|
||||||
'number': fields.IntegerField(),
|
'number': fields.IntegerField(),
|
||||||
'postal_code': fields.KeywordField(),
|
'postal_code': fields.KeywordField(),
|
||||||
'coordinates': fields.GeoPointField(attr='location_field_indexing'),
|
'coordinates': fields.GeoPointField(attr='location_field_indexing'),
|
||||||
# todo: remove if not used
|
|
||||||
'city': fields.ObjectField(
|
'city': fields.ObjectField(
|
||||||
properties={
|
properties={
|
||||||
'id': fields.IntegerField(),
|
'id': fields.IntegerField(),
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,19 @@ class TagsDocumentSerializer(serializers.Serializer):
|
||||||
return get_translated_value(obj.label)
|
return get_translated_value(obj.label)
|
||||||
|
|
||||||
|
|
||||||
|
class CityDocumentShortSerializer(serializers.Serializer):
|
||||||
|
"""City serializer for ES Document,"""
|
||||||
|
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
code = serializers.CharField(allow_null=True)
|
||||||
|
name = serializers.CharField()
|
||||||
|
|
||||||
|
|
||||||
class AddressDocumentSerializer(serializers.Serializer):
|
class AddressDocumentSerializer(serializers.Serializer):
|
||||||
"""Address serializer for ES Document."""
|
"""Address serializer for ES Document."""
|
||||||
|
|
||||||
id = serializers.IntegerField()
|
id = serializers.IntegerField()
|
||||||
|
city = CityDocumentShortSerializer()
|
||||||
street_name_1 = serializers.CharField()
|
street_name_1 = serializers.CharField()
|
||||||
street_name_2 = serializers.CharField()
|
street_name_2 = serializers.CharField()
|
||||||
number = serializers.IntegerField()
|
number = serializers.IntegerField()
|
||||||
|
|
@ -108,6 +117,7 @@ class EstablishmentDocumentSerializer(DocumentSerializer):
|
||||||
'schedule',
|
'schedule',
|
||||||
'works_noon',
|
'works_noon',
|
||||||
'works_evening',
|
'works_evening',
|
||||||
|
'works_at_weekday',
|
||||||
# 'works_now',
|
# 'works_now',
|
||||||
# 'collections',
|
# 'collections',
|
||||||
# 'establishment_type',
|
# 'establishment_type',
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,226 @@
|
||||||
from django_elasticsearch_dsl import fields
|
from django_elasticsearch_dsl import fields
|
||||||
from utils.models import get_current_locale, get_default_locale
|
from utils.models import get_current_locale, get_default_locale
|
||||||
|
|
||||||
|
ALL_LOCALES_LIST = [
|
||||||
|
'af-ZA',
|
||||||
|
'am-ET',
|
||||||
|
'ar-AE',
|
||||||
|
'ar-BH',
|
||||||
|
'ar-DZ',
|
||||||
|
'ar-EG',
|
||||||
|
'ar-IQ',
|
||||||
|
'ar-JO',
|
||||||
|
'ar-KW',
|
||||||
|
'ar-LB',
|
||||||
|
'ar-LY',
|
||||||
|
'ar-MA',
|
||||||
|
'arn-CL',
|
||||||
|
'ar-OM',
|
||||||
|
'ar-QA',
|
||||||
|
'ar-SA',
|
||||||
|
'ar-SY',
|
||||||
|
'ar-TN',
|
||||||
|
'ar-YE',
|
||||||
|
'as-IN',
|
||||||
|
'az-Cyrl-AZ',
|
||||||
|
'az-Latn-AZ',
|
||||||
|
'ba-RU',
|
||||||
|
'be-BY',
|
||||||
|
'bg-BG',
|
||||||
|
'bn-BD',
|
||||||
|
'bn-IN',
|
||||||
|
'bo-CN',
|
||||||
|
'br-FR',
|
||||||
|
'bs-Cyrl-BA',
|
||||||
|
'bs-Latn-BA',
|
||||||
|
'ca-ES',
|
||||||
|
'co-FR',
|
||||||
|
'cs-CZ',
|
||||||
|
'cy-GB',
|
||||||
|
'da-DK',
|
||||||
|
'de-AT',
|
||||||
|
'de-CH',
|
||||||
|
'de-DE',
|
||||||
|
'de-LI',
|
||||||
|
'de-LU',
|
||||||
|
'dsb-DE',
|
||||||
|
'dv-MV',
|
||||||
|
'el-GR',
|
||||||
|
'en-029',
|
||||||
|
'en-AU',
|
||||||
|
'en-BZ',
|
||||||
|
'en-CA',
|
||||||
|
'en-GB',
|
||||||
|
'en-IE',
|
||||||
|
'en-IN',
|
||||||
|
'en-JM',
|
||||||
|
'en-MY',
|
||||||
|
'en-NZ',
|
||||||
|
'en-PH',
|
||||||
|
'en-SG',
|
||||||
|
'en-TT',
|
||||||
|
'en-US',
|
||||||
|
'en-ZA',
|
||||||
|
'en-ZW',
|
||||||
|
'es-AR',
|
||||||
|
'es-BO',
|
||||||
|
'es-CL',
|
||||||
|
'es-CO',
|
||||||
|
'es-CR',
|
||||||
|
'es-DO',
|
||||||
|
'es-EC',
|
||||||
|
'es-ES',
|
||||||
|
'es-GT',
|
||||||
|
'es-HN',
|
||||||
|
'es-MX',
|
||||||
|
'es-NI',
|
||||||
|
'es-PA',
|
||||||
|
'es-PE',
|
||||||
|
'es-PR',
|
||||||
|
'es-PY',
|
||||||
|
'es-SV',
|
||||||
|
'es-US',
|
||||||
|
'es-UY',
|
||||||
|
'es-VE',
|
||||||
|
'et-EE',
|
||||||
|
'eu-ES',
|
||||||
|
'fa-IR',
|
||||||
|
'fi-FI',
|
||||||
|
'fil-PH',
|
||||||
|
'fo-FO',
|
||||||
|
'fr-BE',
|
||||||
|
'fr-CA',
|
||||||
|
'fr-CH',
|
||||||
|
'fr-FR',
|
||||||
|
'fr-LU',
|
||||||
|
'fr-MC',
|
||||||
|
'fy-NL',
|
||||||
|
'ga-IE',
|
||||||
|
'gd-GB',
|
||||||
|
'gl-ES',
|
||||||
|
'gsw-FR',
|
||||||
|
'gu-IN',
|
||||||
|
'ha-Latn-NG',
|
||||||
|
'he-IL',
|
||||||
|
'hi-IN',
|
||||||
|
'hr-BA',
|
||||||
|
'hr-HR',
|
||||||
|
'hsb-DE',
|
||||||
|
'hu-HU',
|
||||||
|
'hy-AM',
|
||||||
|
'id-ID',
|
||||||
|
'ig-NG',
|
||||||
|
'ii-CN',
|
||||||
|
'is-IS',
|
||||||
|
'it-CH',
|
||||||
|
'it-IT',
|
||||||
|
'iu-Cans-CA',
|
||||||
|
'iu-Latn-CA',
|
||||||
|
'ja-JP',
|
||||||
|
'ka-GE',
|
||||||
|
'kk-KZ',
|
||||||
|
'kl-GL',
|
||||||
|
'km-KH',
|
||||||
|
'kn-IN',
|
||||||
|
'kok-IN',
|
||||||
|
'ko-KR',
|
||||||
|
'ky-KG',
|
||||||
|
'lb-LU',
|
||||||
|
'lo-LA',
|
||||||
|
'lt-LT',
|
||||||
|
'lv-LV',
|
||||||
|
'mi-NZ',
|
||||||
|
'mk-MK',
|
||||||
|
'ml-IN',
|
||||||
|
'mn-MN',
|
||||||
|
'mn-Mong-CN',
|
||||||
|
'moh-CA',
|
||||||
|
'mr-IN',
|
||||||
|
'ms-BN',
|
||||||
|
'ms-MY',
|
||||||
|
'mt-MT',
|
||||||
|
'nb-NO',
|
||||||
|
'ne-NP',
|
||||||
|
'nl-BE',
|
||||||
|
'nl-NL',
|
||||||
|
'nn-NO',
|
||||||
|
'nso-ZA',
|
||||||
|
'oc-FR',
|
||||||
|
'or-IN',
|
||||||
|
'pa-IN',
|
||||||
|
'pl-PL',
|
||||||
|
'prs-AF',
|
||||||
|
'ps-AF',
|
||||||
|
'pt-BR',
|
||||||
|
'pt-PT',
|
||||||
|
'qut-GT',
|
||||||
|
'quz-BO',
|
||||||
|
'quz-EC',
|
||||||
|
'quz-PE',
|
||||||
|
'rm-CH',
|
||||||
|
'ro-RO',
|
||||||
|
'ru-RU',
|
||||||
|
'rw-RW',
|
||||||
|
'sah-RU',
|
||||||
|
'sa-IN',
|
||||||
|
'se-FI',
|
||||||
|
'se-NO',
|
||||||
|
'se-SE',
|
||||||
|
'si-LK',
|
||||||
|
'sk-SK',
|
||||||
|
'sl-SI',
|
||||||
|
'sma-NO',
|
||||||
|
'sma-SE',
|
||||||
|
'smj-NO',
|
||||||
|
'smj-SE',
|
||||||
|
'smn-FI',
|
||||||
|
'sms-FI',
|
||||||
|
'sq-AL',
|
||||||
|
'sr-Cyrl-BA',
|
||||||
|
'sr-Cyrl-CS',
|
||||||
|
'sr-Cyrl-ME',
|
||||||
|
'sr-Cyrl-RS',
|
||||||
|
'sr-Latn-BA',
|
||||||
|
'sr-Latn-CS',
|
||||||
|
'sr-Latn-ME',
|
||||||
|
'sr-Latn-RS',
|
||||||
|
'sv-FI',
|
||||||
|
'sv-SE',
|
||||||
|
'sw-KE',
|
||||||
|
'syr-SY',
|
||||||
|
'ta-IN',
|
||||||
|
'te-IN',
|
||||||
|
'tg-Cyrl-TJ',
|
||||||
|
'th-TH',
|
||||||
|
'tk-TM',
|
||||||
|
'tn-ZA',
|
||||||
|
'tr-TR',
|
||||||
|
'tt-RU',
|
||||||
|
'tzm-Latn-DZ',
|
||||||
|
'ug-CN',
|
||||||
|
'uk-UA',
|
||||||
|
'ur-PK',
|
||||||
|
'uz-Cyrl-UZ',
|
||||||
|
'uz-Latn-UZ',
|
||||||
|
'vi-VN',
|
||||||
|
'wo-SN',
|
||||||
|
'xh-ZA',
|
||||||
|
'yo-NG',
|
||||||
|
'zh-CN',
|
||||||
|
'zh-HK',
|
||||||
|
'zh-MO',
|
||||||
|
'zh-SG',
|
||||||
|
'zh-TW',
|
||||||
|
'zu-ZA',
|
||||||
|
]
|
||||||
|
|
||||||
# object field properties
|
# object field properties
|
||||||
OBJECT_FIELD_PROPERTIES = {
|
OBJECT_FIELD_PROPERTIES = {locale: fields.TextField() for locale in ALL_LOCALES_LIST}
|
||||||
|
OBJECT_FIELD_PROPERTIES.update({
|
||||||
'en-GB': fields.TextField(analyzer='english'),
|
'en-GB': fields.TextField(analyzer='english'),
|
||||||
'ru-RU': fields.TextField(analyzer='russian'),
|
'ru-RU': fields.TextField(analyzer='russian'),
|
||||||
'fr-FR': fields.TextField(analyzer='french'),
|
'fr-FR': fields.TextField(analyzer='french')
|
||||||
}
|
})
|
||||||
|
|
||||||
|
|
||||||
# todo: refactor serializer
|
# todo: refactor serializer
|
||||||
|
|
@ -17,10 +230,14 @@ def get_translated_value(value):
|
||||||
return None
|
return None
|
||||||
elif not isinstance(value, dict):
|
elif not isinstance(value, dict):
|
||||||
field_dict = value.to_dict()
|
field_dict = value.to_dict()
|
||||||
elif isinstance(value, dict):
|
else:
|
||||||
field_dict = value
|
field_dict = value
|
||||||
value = field_dict.get(get_current_locale())
|
field_dict = {k: v for k, v in field_dict.items() if v is not None}
|
||||||
|
result = field_dict.get(get_current_locale(), None)
|
||||||
# fallback
|
# fallback
|
||||||
if value is None:
|
if result is None:
|
||||||
value = field_dict.get(get_default_locale())
|
result = field_dict.get(get_default_locale(), None)
|
||||||
return value
|
if result is None:
|
||||||
|
values = list(field_dict.values())
|
||||||
|
result = values[0] if values else None
|
||||||
|
return result
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,12 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
|
||||||
constants.LOOKUP_QUERY_IN,
|
constants.LOOKUP_QUERY_IN,
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
'works_at_weekday': {
|
||||||
|
'field': 'works_at_weekday',
|
||||||
|
'lookups': [
|
||||||
|
constants.LOOKUP_QUERY_IN,
|
||||||
|
],
|
||||||
|
},
|
||||||
'works_evening': {
|
'works_evening': {
|
||||||
'field': 'works_evening',
|
'field': 'works_evening',
|
||||||
'lookups': [
|
'lookups': [
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ class Command(BaseCommand):
|
||||||
'en-GB': key_value.key_name,
|
'en-GB': key_value.key_name,
|
||||||
'fr-FR': key_value.key_name,
|
'fr-FR': key_value.key_name,
|
||||||
'ru-RU': key_value.key_name,
|
'ru-RU': key_value.key_name,
|
||||||
},
|
}
|
||||||
tag_category.value_type = key_value.value_type
|
tag_category.value_type = key_value.value_type
|
||||||
tag_category.save()
|
tag_category.save()
|
||||||
est_type.tag_categories.add(
|
est_type.tag_categories.add(
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,7 @@ class TagBackOfficeSerializer(TagBaseSerializer):
|
||||||
class TagCategoryBaseSerializer(serializers.ModelSerializer):
|
class TagCategoryBaseSerializer(serializers.ModelSerializer):
|
||||||
"""Serializer for model TagCategory."""
|
"""Serializer for model TagCategory."""
|
||||||
|
|
||||||
# todo: refactor this
|
label_translated = TranslatedField()
|
||||||
# label_translated = TranslatedField()
|
|
||||||
label_translated = serializers.CharField(source='index_name', read_only=True, allow_null=True)
|
|
||||||
tags = TagBaseSerializer(many=True, read_only=True)
|
tags = TagBaseSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ card = {
|
||||||
"fields": {
|
"fields": {
|
||||||
"Schedules": {
|
"Schedules": {
|
||||||
# нет аналогов для weekday, opening_at, closed_at
|
# нет аналогов для weekday, opening_at, closed_at
|
||||||
|
# upd: запустить команду add_closed_at_timetable. она заполнит opening_at, closed_at
|
||||||
"lunch_start": "lunch_start",
|
"lunch_start": "lunch_start",
|
||||||
"lunch_end": "lunch_end",
|
"lunch_end": "lunch_end",
|
||||||
"diner_start": "diner_start",
|
"diner_start": "diner_start",
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,9 @@ class Command(BaseCommand):
|
||||||
'inquiries', # №6 - перенос запросов оценок
|
'inquiries', # №6 - перенос запросов оценок
|
||||||
'wine_characteristics',
|
'wine_characteristics',
|
||||||
'product',
|
'product',
|
||||||
'product_description',
|
'product_note',
|
||||||
'souvenir',
|
'souvenir',
|
||||||
|
'establishment_note',
|
||||||
]
|
]
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
|
|
||||||
|
|
@ -447,6 +447,18 @@ class Establishments(MigrateMixin):
|
||||||
db_table = 'establishments'
|
db_table = 'establishments'
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentNotes(MigrateMixin):
|
||||||
|
using = 'legacy'
|
||||||
|
|
||||||
|
establishment_id = models.IntegerField(null=True, blank=True)
|
||||||
|
account_id = models.IntegerField(null=True, blank=True)
|
||||||
|
text = models.TextField(null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
managed = False
|
||||||
|
db_table = 'notes'
|
||||||
|
|
||||||
|
|
||||||
class Descriptions(MigrateMixin):
|
class Descriptions(MigrateMixin):
|
||||||
using = 'legacy'
|
using = 'legacy'
|
||||||
|
|
||||||
|
|
@ -973,7 +985,7 @@ class Products(MigrateMixin):
|
||||||
class ProductNotes(MigrateMixin):
|
class ProductNotes(MigrateMixin):
|
||||||
using = 'legacy'
|
using = 'legacy'
|
||||||
|
|
||||||
product_id = models.ForeignKey(Products, on_delete=models.DO_NOTHING)
|
product_id = models.IntegerField(null=True, blank=True)
|
||||||
text = models.CharField(max_length=255)
|
text = models.CharField(max_length=255)
|
||||||
win_import_id = models.CharField(max_length=255)
|
win_import_id = models.CharField(max_length=255)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from comment.models import Comment, User
|
from comment.models import Comment, User
|
||||||
from establishment.models import Establishment
|
from establishment.models import Establishment
|
||||||
from location.models import Country
|
|
||||||
|
|
||||||
|
|
||||||
class CommentSerializer(serializers.Serializer):
|
class CommentSerializer(serializers.Serializer):
|
||||||
id = serializers.IntegerField()
|
id = serializers.IntegerField()
|
||||||
comment = serializers.CharField()
|
comment = serializers.CharField()
|
||||||
mark = serializers.DecimalField(max_digits=4, decimal_places=2)
|
mark = serializers.DecimalField(max_digits=4, decimal_places=2, allow_null=True)
|
||||||
locale = serializers.CharField()
|
|
||||||
account_id = serializers.IntegerField()
|
account_id = serializers.IntegerField()
|
||||||
establishment_id = serializers.CharField()
|
establishment_id = serializers.CharField()
|
||||||
|
|
||||||
|
|
@ -16,14 +15,12 @@ class CommentSerializer(serializers.Serializer):
|
||||||
data.update({
|
data.update({
|
||||||
'old_id': data.pop('id'),
|
'old_id': data.pop('id'),
|
||||||
'text': data.pop('comment'),
|
'text': data.pop('comment'),
|
||||||
'mark': data['mark'] * -1 if data['mark'] < 0 else data['mark'],
|
'mark': self.get_mark(data),
|
||||||
'content_object': self.get_content_object(data),
|
'content_object': self.get_content_object(data),
|
||||||
'user': self.get_account(data),
|
'user': self.get_account(data),
|
||||||
'country': self.get_country(data),
|
|
||||||
})
|
})
|
||||||
data.pop('establishment_id')
|
data.pop('establishment_id')
|
||||||
data.pop('account_id')
|
data.pop('account_id')
|
||||||
data.pop('locale')
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
|
@ -47,10 +44,7 @@ class CommentSerializer(serializers.Serializer):
|
||||||
return user
|
return user
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_country(data):
|
def get_mark(data):
|
||||||
locale = data['locale']
|
if not data['mark']:
|
||||||
country_code = locale[:locale.index("-")] if len(locale) > 2 else locale
|
return None
|
||||||
country = Country.objects.filter(code=country_code).first()
|
return data['mark'] * -1 if data['mark'] < 0 else data['mark']
|
||||||
if not country:
|
|
||||||
raise ValueError(f"Country not found with code {country_code}")
|
|
||||||
return country
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import MultipleObjectsReturned, ValidationError
|
from django.core.exceptions import MultipleObjectsReturned, ValidationError
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
from django.utils.text import slugify
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from establishment.models import Establishment, ContactEmail, ContactPhone, EstablishmentType, \
|
from account.models import User
|
||||||
EstablishmentSubType
|
from establishment.models import Establishment, ContactEmail, ContactPhone, \
|
||||||
|
EstablishmentType, EstablishmentSubType, EstablishmentNote
|
||||||
from location.models import Address
|
from location.models import Address
|
||||||
from timetable.models import Timetable
|
from timetable.models import Timetable
|
||||||
from utils.legacy_parser import parse_legacy_schedule_content
|
from utils.legacy_parser import parse_legacy_schedule_content
|
||||||
from utils.serializers import TimeZoneChoiceField
|
from utils.serializers import TimeZoneChoiceField
|
||||||
from utils.slug_generator import generate_unique_slug
|
from utils.slug_generator import generate_unique_slug
|
||||||
from django.utils.text import slugify
|
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentSerializer(serializers.ModelSerializer):
|
class EstablishmentSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -173,3 +174,45 @@ class EstablishmentSerializer(serializers.ModelSerializer):
|
||||||
index_name=slugify(subtype_name),
|
index_name=slugify(subtype_name),
|
||||||
establishment_type_id=establishment_type_id)
|
establishment_type_id=establishment_type_id)
|
||||||
return subtype
|
return subtype
|
||||||
|
|
||||||
|
|
||||||
|
class EstablishmentNoteSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
establishment_id = serializers.IntegerField()
|
||||||
|
account_id = serializers.IntegerField(allow_null=True)
|
||||||
|
text = serializers.CharField(allow_blank=True, allow_null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = EstablishmentNote
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'establishment_id',
|
||||||
|
'account_id',
|
||||||
|
'text',
|
||||||
|
)
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
attrs['old_id'] = attrs['id']
|
||||||
|
attrs['establishment'] = self.get_establishment(attrs.pop('establishment_id'))
|
||||||
|
attrs['user'] = self.get_user(attrs.pop('account_id'))
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
qs = self.Meta.model.objects.filter(**validated_data)
|
||||||
|
establishment = validated_data.get('establishment')
|
||||||
|
|
||||||
|
if not qs.exists() and establishment:
|
||||||
|
obj = super().create(validated_data)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def get_establishment(self, old_id):
|
||||||
|
if old_id:
|
||||||
|
qs = Establishment.objects.filter(old_id=old_id)
|
||||||
|
if qs.exists():
|
||||||
|
return qs.first()
|
||||||
|
|
||||||
|
def get_user(self, old_id):
|
||||||
|
qs = User.objects.exclude(old_id__isnull=True).filter(old_id=old_id)
|
||||||
|
if qs.exists():
|
||||||
|
return qs.first()
|
||||||
|
|
|
||||||
|
|
@ -541,3 +541,36 @@ class PlateImageSerializer(serializers.ModelSerializer):
|
||||||
product_qs = models.Product.objects.filter(old_id=product_id)
|
product_qs = models.Product.objects.filter(old_id=product_id)
|
||||||
if product_qs.exists():
|
if product_qs.exists():
|
||||||
return product_qs.first()
|
return product_qs.first()
|
||||||
|
|
||||||
|
|
||||||
|
class ProductNoteSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
id = serializers.IntegerField()
|
||||||
|
product_id = serializers.IntegerField()
|
||||||
|
text = serializers.CharField(allow_blank=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = models.ProductNote
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'product_id',
|
||||||
|
'text',
|
||||||
|
)
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
attrs['old_id'] = attrs['id']
|
||||||
|
attrs['product'] = self.get_product(attrs.pop('product_id'))
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
qs = self.Meta.model.objects.filter(**validated_data)
|
||||||
|
product = validated_data.get('product')
|
||||||
|
|
||||||
|
if not qs.exists() and product:
|
||||||
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
def get_product(self, old_id):
|
||||||
|
if old_id:
|
||||||
|
qs = models.Product.objects.filter(old_id=old_id)
|
||||||
|
if qs.exists():
|
||||||
|
return qs.first()
|
||||||
|
|
|
||||||
|
|
@ -98,3 +98,9 @@ class FavoritesCreateSerializer(serializers.ModelSerializer):
|
||||||
@property
|
@property
|
||||||
def slug(self):
|
def slug(self):
|
||||||
return self.request.parser_context.get('kwargs').get('slug')
|
return self.request.parser_context.get('kwargs').get('slug')
|
||||||
|
|
||||||
|
|
||||||
|
class RecursiveFieldSerializer(serializers.Serializer):
|
||||||
|
def to_representation(self, value):
|
||||||
|
serializer = self.parent.parent.__class__(value, context=self.context)
|
||||||
|
return serializer.data
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,6 @@ urlpatterns = [
|
||||||
# path('advertisement/', include('advertisement.urls.web')),
|
# path('advertisement/', include('advertisement.urls.web')),
|
||||||
# path('collection/', include('collection.urls.web')),
|
# path('collection/', include('collection.urls.web')),
|
||||||
# path('establishments/', include('establishment.urls.web')),
|
# path('establishments/', include('establishment.urls.web')),
|
||||||
# path('news/', include('news.urls.web')),
|
path('news/', include('news.urls.mobile')),
|
||||||
# path('partner/', include('partner.urls.web')),
|
# path('partner/', include('partner.urls.web')),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user