Merge branch 'develop' into fix/user-role-err
This commit is contained in:
commit
933f21cdaa
113
.dockerignore
Normal file
113
.dockerignore
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
### Python template
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
|
||||||
|
_*/
|
||||||
|
|
||||||
|
.git/
|
||||||
|
.idea/
|
||||||
|
_files/
|
||||||
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
FROM python:3.7
|
FROM python:3.7
|
||||||
ENV PYTHONUNBUFFERED 1
|
ENV PYTHONUNBUFFERED 1
|
||||||
RUN apt-get update; apt-get --assume-yes install binutils libproj-dev gdal-bin gettext
|
RUN apt-get update; apt-get --assume-yes install binutils libproj-dev gdal-bin gettext
|
||||||
RUN mkdir /code
|
RUN mkdir /code /requirements
|
||||||
|
ADD ./requirements /requirements
|
||||||
|
RUN pip install --no-cache-dir -r /requirements/base.txt && \
|
||||||
|
pip install --no-cache-dir -r /requirements/development.txt
|
||||||
WORKDIR /code
|
WORKDIR /code
|
||||||
ADD . /code/
|
ADD . /code/
|
||||||
RUN pip install --no-cache-dir -r /code/requirements/base.txt && \
|
|
||||||
pip install --no-cache-dir -r /code/requirements/development.txt
|
|
||||||
|
|
@ -92,7 +92,11 @@ class UserBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
model = models.User
|
model = models.User
|
||||||
fields = (
|
fields = (
|
||||||
|
'id',
|
||||||
'fullname',
|
'fullname',
|
||||||
|
'first_name',
|
||||||
|
'last_name',
|
||||||
|
'email',
|
||||||
'cropped_image_url',
|
'cropped_image_url',
|
||||||
'image_url',
|
'image_url',
|
||||||
)
|
)
|
||||||
|
|
|
||||||
36
apps/establishment/management/commands/fix_scheduler.py
Normal file
36
apps/establishment/management/commands/fix_scheduler.py
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from establishment.models import Establishment
|
||||||
|
from transfer.models import Establishments
|
||||||
|
from transfer.serializers.establishment import EstablishmentSerializer
|
||||||
|
from timetable.models import Timetable
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Fix scheduler'
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
count = 0
|
||||||
|
establishments = Establishment.objects.all()
|
||||||
|
old_est_list = Establishments.objects.prefetch_related(
|
||||||
|
'schedules_set',
|
||||||
|
)
|
||||||
|
# remove old records of Timetable
|
||||||
|
Timetable.objects.all().delete()
|
||||||
|
|
||||||
|
for est in tqdm(establishments, desc="Fix scheduler"):
|
||||||
|
old_est = old_est_list.filter(id=est.old_id).first()
|
||||||
|
|
||||||
|
if old_est and old_est.schedules_set.exists():
|
||||||
|
old_schedule = old_est.schedules_set.first()
|
||||||
|
timetable = old_schedule.timetable
|
||||||
|
if timetable:
|
||||||
|
new_schedules = EstablishmentSerializer.get_schedules(timetable)
|
||||||
|
est.schedule.add(*new_schedules)
|
||||||
|
est.save()
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
self.stdout.write(self.style.WARNING(f'Update {count} objects.'))
|
||||||
|
|
@ -14,7 +14,7 @@ from django.contrib.postgres.fields import ArrayField
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import MinValueValidator, MaxValueValidator
|
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q
|
from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q, Prefetch
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from phonenumber_field.modelfields import PhoneNumberField
|
from phonenumber_field.modelfields import PhoneNumberField
|
||||||
|
|
@ -23,6 +23,7 @@ from timezone_field import TimeZoneField
|
||||||
from collection.models import Collection
|
from collection.models import Collection
|
||||||
from location.models import Address
|
from location.models import Address
|
||||||
from main.models import Award, Currency
|
from main.models import Award, Currency
|
||||||
|
from tag.models import Tag
|
||||||
from review.models import Review
|
from review.models import Review
|
||||||
from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin,
|
from utils.models import (ProjectBaseMixin, TJSONField, URLImageMixin,
|
||||||
TranslatedFieldsMixin, BaseAttributes, GalleryModelMixin,
|
TranslatedFieldsMixin, BaseAttributes, GalleryModelMixin,
|
||||||
|
|
@ -321,6 +322,13 @@ class EstablishmentQuerySet(models.QuerySet):
|
||||||
"""Exclude countries."""
|
"""Exclude countries."""
|
||||||
return self.exclude(address__city__country__in=countries)
|
return self.exclude(address__city__country__in=countries)
|
||||||
|
|
||||||
|
def with_certain_tag_category_related(self, index_name, attr_name):
|
||||||
|
"""Includes extra tags."""
|
||||||
|
return self.prefetch_related(
|
||||||
|
Prefetch('tags', queryset=Tag.objects.filter(category__index_name=index_name),
|
||||||
|
to_attr=attr_name)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin,
|
class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin,
|
||||||
TranslatedFieldsMixin, HasTagsMixin, FavoritesMixin):
|
TranslatedFieldsMixin, HasTagsMixin, FavoritesMixin):
|
||||||
|
|
@ -541,6 +549,11 @@ class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin,
|
||||||
time_at_est_tz = now_at_est_tz.time()
|
time_at_est_tz = now_at_est_tz.time()
|
||||||
return schedule_for_today.ending_time > time_at_est_tz > schedule_for_today.opening_time
|
return schedule_for_today.ending_time > time_at_est_tz > schedule_for_today.opening_time
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timezone_as_str(self):
|
||||||
|
""" Returns tz in str format"""
|
||||||
|
return self.tz.localize(datetime.now()).strftime('%z')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tags_indexing(self):
|
def tags_indexing(self):
|
||||||
return [{'id': tag.metadata.id,
|
return [{'id': tag.metadata.id,
|
||||||
|
|
@ -589,6 +602,18 @@ class Establishment(GalleryModelMixin, ProjectBaseMixin, URLImageMixin,
|
||||||
if qs.exists():
|
if qs.exists():
|
||||||
return qs.first().image
|
return qs.first().image
|
||||||
|
|
||||||
|
@property
|
||||||
|
def restaurant_category_indexing(self):
|
||||||
|
return self.tags.filter(category__index_name='category')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def restaurant_cuisine_indexing(self):
|
||||||
|
return self.tags.filter(category__index_name='cuisine')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def artisan_category_indexing(self):
|
||||||
|
return self.tags.filter(category__index_name='shop_category')
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentNoteQuerySet(models.QuerySet):
|
class EstablishmentNoteQuerySet(models.QuerySet):
|
||||||
"""QuerySet for model EstablishmentNote."""
|
"""QuerySet for model EstablishmentNote."""
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
|
||||||
preview_image = serializers.URLField(source='preview_image_url',
|
preview_image = serializers.URLField(source='preview_image_url',
|
||||||
allow_null=True,
|
allow_null=True,
|
||||||
read_only=True)
|
read_only=True)
|
||||||
|
tz = serializers.CharField(read_only=True, source='timezone_as_str')
|
||||||
new_image = ImageBaseSerializer(source='crop_main_image', allow_null=True, read_only=True)
|
new_image = ImageBaseSerializer(source='crop_main_image', allow_null=True, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -311,6 +311,7 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
|
||||||
'image',
|
'image',
|
||||||
'preview_image',
|
'preview_image',
|
||||||
'new_image',
|
'new_image',
|
||||||
|
'tz',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -319,12 +320,18 @@ class EstablishmentListRetrieveSerializer(EstablishmentBaseSerializer):
|
||||||
|
|
||||||
address = AddressDetailSerializer()
|
address = AddressDetailSerializer()
|
||||||
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
schedule = ScheduleRUDSerializer(many=True, allow_null=True)
|
||||||
|
restaurant_category = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
||||||
|
restaurant_cuisine = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
||||||
|
artisan_category = TagBaseSerializer(read_only=True, many=True, allow_null=True)
|
||||||
|
|
||||||
class Meta(EstablishmentBaseSerializer.Meta):
|
class Meta(EstablishmentBaseSerializer.Meta):
|
||||||
"""Meta class."""
|
"""Meta class."""
|
||||||
|
|
||||||
fields = EstablishmentBaseSerializer.Meta.fields + [
|
fields = EstablishmentBaseSerializer.Meta.fields + [
|
||||||
'schedule',
|
'schedule',
|
||||||
|
'restaurant_category',
|
||||||
|
'restaurant_cuisine',
|
||||||
|
'artisan_category',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,10 @@ class EstablishmentListView(EstablishmentMixinView, generics.ListAPIView):
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().with_schedule() \
|
return super().get_queryset().with_schedule() \
|
||||||
.with_extended_address_related().with_currency_related()
|
.with_extended_address_related().with_currency_related() \
|
||||||
|
.with_certain_tag_category_related('category', 'restaurant_category') \
|
||||||
|
.with_certain_tag_category_related('cuisine', 'restaurant_cuisine') \
|
||||||
|
.with_certain_tag_category_related('shop_category', 'artisan_category')
|
||||||
|
|
||||||
|
|
||||||
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
class EstablishmentRetrieveView(EstablishmentMixinView, generics.RetrieveAPIView):
|
||||||
|
|
|
||||||
|
|
@ -21,27 +21,6 @@ class FeatureSerializer(serializers.ModelSerializer):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class SiteFeatureSerializer(serializers.ModelSerializer):
|
|
||||||
id = serializers.IntegerField(source='feature.id')
|
|
||||||
slug = serializers.CharField(source='feature.slug')
|
|
||||||
priority = serializers.IntegerField(source='feature.priority')
|
|
||||||
route = serializers.CharField(source='feature.route.name')
|
|
||||||
source = serializers.IntegerField(source='feature.source')
|
|
||||||
nested = RecursiveFieldSerializer(many=True, allow_null=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
"""Meta class."""
|
|
||||||
model = models.SiteFeature
|
|
||||||
fields = ('main',
|
|
||||||
'id',
|
|
||||||
'slug',
|
|
||||||
'priority',
|
|
||||||
'route',
|
|
||||||
'source',
|
|
||||||
'nested',
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CurrencySerializer(ProjectModelSerializer):
|
class CurrencySerializer(ProjectModelSerializer):
|
||||||
"""Currency serializer."""
|
"""Currency serializer."""
|
||||||
|
|
||||||
|
|
@ -56,6 +35,23 @@ class CurrencySerializer(ProjectModelSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class SiteFeatureSerializer(serializers.ModelSerializer):
|
||||||
|
"""Site feature serializer."""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
"""Meta class."""
|
||||||
|
|
||||||
|
model = models.SiteFeature
|
||||||
|
fields = (
|
||||||
|
'id',
|
||||||
|
'site_settings',
|
||||||
|
'feature',
|
||||||
|
'published',
|
||||||
|
'main',
|
||||||
|
'nested'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SiteSettingsSerializer(serializers.ModelSerializer):
|
class SiteSettingsSerializer(serializers.ModelSerializer):
|
||||||
"""Site settings serializer."""
|
"""Site settings serializer."""
|
||||||
|
|
||||||
|
|
@ -108,7 +104,14 @@ class SiteSerializer(serializers.ModelSerializer):
|
||||||
fields = [
|
fields = [
|
||||||
'subdomain',
|
'subdomain',
|
||||||
'site_url',
|
'site_url',
|
||||||
'country'
|
'country',
|
||||||
|
'default_site',
|
||||||
|
'pinterest_page_url',
|
||||||
|
'twitter_page_url',
|
||||||
|
'facebook_page_url',
|
||||||
|
'instagram_page_url',
|
||||||
|
'contact_email',
|
||||||
|
'currency'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -132,19 +135,20 @@ class SiteBackOfficeSerializer(SiteSerializer):
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# class SiteFeatureSerializer(serializers.ModelSerializer):
|
class FeatureSerializer(serializers.ModelSerializer):
|
||||||
# """Site feature serializer."""
|
"""Feature serializer."""
|
||||||
#
|
|
||||||
# class Meta:
|
class Meta:
|
||||||
# """Meta class."""
|
"""Meta class."""
|
||||||
#
|
|
||||||
# model = models.SiteFeature
|
model = models.Feature
|
||||||
# fields = (
|
fields = (
|
||||||
# 'id',
|
'id',
|
||||||
# 'published',
|
'slug',
|
||||||
# 'site_settings',
|
'priority',
|
||||||
# 'feature',
|
'route',
|
||||||
# )
|
'site_settings',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class AwardBaseSerializer(serializers.ModelSerializer):
|
class AwardBaseSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,15 @@ urlpatterns = [
|
||||||
path('awards/', views.AwardLstView.as_view(), name='awards-list-create'),
|
path('awards/', views.AwardLstView.as_view(), name='awards-list-create'),
|
||||||
path('awards/<int:id>/', views.AwardRUDView.as_view(), name='awards-rud'),
|
path('awards/<int:id>/', views.AwardRUDView.as_view(), name='awards-rud'),
|
||||||
path('content_type/', views.ContentTypeView.as_view(), name='content_type-list'),
|
path('content_type/', views.ContentTypeView.as_view(), name='content_type-list'),
|
||||||
path('sites/', views.SiteListBackOfficeView.as_view(), name='site-list'),
|
path('sites/', views.SiteListBackOfficeView.as_view(), name='site-list-create'),
|
||||||
path('site-settings/<subdomain>/', views.SiteSettingsBackOfficeView.as_view(),
|
path('site-settings/<subdomain>/', views.SiteSettingsBackOfficeView.as_view(),
|
||||||
name='site-settings'),
|
name='site-settings'),
|
||||||
|
path('feature/', views.FeatureBackView.as_view(), name='feature-list-create'),
|
||||||
|
path('feature/<int:id>/', views.FeatureRUDBackView.as_view(), name='feature-rud'),
|
||||||
|
path('site-feature/', views.SiteFeatureBackView.as_view(),
|
||||||
|
name='site-feature-list-create'),
|
||||||
|
path('site-feature/<int:id>/', views.SiteFeatureRUDBackView.as_view(),
|
||||||
|
name='site-feature-rud'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,26 @@ class ContentTypeView(generics.ListAPIView):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureBackView(generics.ListCreateAPIView):
|
||||||
|
"""Feature list or create View."""
|
||||||
|
serializer_class = serializers.FeatureSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class SiteFeatureBackView(generics.ListCreateAPIView):
|
||||||
|
"""Feature list or create View."""
|
||||||
|
serializer_class = serializers.SiteFeatureSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class FeatureRUDBackView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
|
"""Feature RUD View."""
|
||||||
|
serializer_class = serializers.FeatureSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class SiteFeatureRUDBackView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
|
"""Feature RUD View."""
|
||||||
|
serializer_class = serializers.SiteFeatureSerializer
|
||||||
|
|
||||||
|
|
||||||
class SiteSettingsBackOfficeView(SiteSettingsView):
|
class SiteSettingsBackOfficeView(SiteSettingsView):
|
||||||
"""Site settings View."""
|
"""Site settings View."""
|
||||||
serializer_class = serializers.SiteSettingsBackOfficeSerializer
|
serializer_class = serializers.SiteSettingsBackOfficeSerializer
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class DetermineSiteView(generics.GenericAPIView):
|
||||||
return Response(data={'url': url})
|
return Response(data={'url': url})
|
||||||
|
|
||||||
|
|
||||||
class SiteSettingsView(generics.RetrieveAPIView):
|
class SiteSettingsView(generics.RetrieveUpdateDestroyAPIView):
|
||||||
"""Site settings View."""
|
"""Site settings View."""
|
||||||
|
|
||||||
lookup_field = 'subdomain'
|
lookup_field = 'subdomain'
|
||||||
|
|
@ -28,7 +28,7 @@ class SiteSettingsView(generics.RetrieveAPIView):
|
||||||
serializer_class = serializers.SiteSettingsBackOfficeSerializer
|
serializer_class = serializers.SiteSettingsBackOfficeSerializer
|
||||||
|
|
||||||
|
|
||||||
class SiteListView(generics.ListAPIView):
|
class SiteListView(generics.ListCreateAPIView):
|
||||||
"""Site settings View."""
|
"""Site settings View."""
|
||||||
|
|
||||||
pagination_class = None
|
pagination_class = None
|
||||||
|
|
|
||||||
29
apps/news/management/commands/add_author.py
Normal file
29
apps/news/management/commands/add_author.py
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.db.models import F
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from account.models import User
|
||||||
|
from news.models import News
|
||||||
|
from transfer.models import PageTexts
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Add author of News'
|
||||||
|
|
||||||
|
def handle(self, *args, **kwargs):
|
||||||
|
count = 0
|
||||||
|
news_list = News.objects.filter(created_by__isnull=True)
|
||||||
|
|
||||||
|
for news in tqdm(news_list, desc="Find author for exist news"):
|
||||||
|
old_news = PageTexts.objects.filter(id=news.old_id).annotate(
|
||||||
|
account_id=F('page__account_id'),
|
||||||
|
).first()
|
||||||
|
if old_news:
|
||||||
|
user = User.objects.filter(old_id=old_news.account_id).first()
|
||||||
|
if user:
|
||||||
|
news.created_by = user
|
||||||
|
news.modified_by = user
|
||||||
|
news.save()
|
||||||
|
count += 1
|
||||||
|
|
||||||
|
self.stdout.write(self.style.WARNING(f'Update {count} objects.'))
|
||||||
|
|
@ -38,6 +38,7 @@ def transfer_news():
|
||||||
image=F('page__attachment_suffix_url'),
|
image=F('page__attachment_suffix_url'),
|
||||||
template=F('page__template'),
|
template=F('page__template'),
|
||||||
tags=GroupConcat('page__tags__id'),
|
tags=GroupConcat('page__tags__id'),
|
||||||
|
account_id=F('page__account_id'),
|
||||||
)
|
)
|
||||||
|
|
||||||
serialized_data = NewsSerializer(data=list(queryset.values()), many=True)
|
serialized_data = NewsSerializer(data=list(queryset.values()), many=True)
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,30 @@ class EstablishmentDocument(Document):
|
||||||
'value': fields.KeywordField(),
|
'value': fields.KeywordField(),
|
||||||
},
|
},
|
||||||
multi=True)
|
multi=True)
|
||||||
|
restaurant_category = fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'id': fields.IntegerField(attr='id'),
|
||||||
|
'label': fields.ObjectField(attr='label_indexing',
|
||||||
|
properties=OBJECT_FIELD_PROPERTIES),
|
||||||
|
'value': fields.KeywordField(),
|
||||||
|
},
|
||||||
|
multi=True, attr='restaurant_category_indexing')
|
||||||
|
restaurant_cuisine = fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'id': fields.IntegerField(attr='id'),
|
||||||
|
'label': fields.ObjectField(attr='label_indexing',
|
||||||
|
properties=OBJECT_FIELD_PROPERTIES),
|
||||||
|
'value': fields.KeywordField(),
|
||||||
|
},
|
||||||
|
multi=True, attr='restaurant_cuisine_indexing')
|
||||||
|
artisan_category = fields.ObjectField(
|
||||||
|
properties={
|
||||||
|
'id': fields.IntegerField(attr='id'),
|
||||||
|
'label': fields.ObjectField(attr='label_indexing',
|
||||||
|
properties=OBJECT_FIELD_PROPERTIES),
|
||||||
|
'value': fields.KeywordField(),
|
||||||
|
},
|
||||||
|
multi=True, attr='artisan_category_indexing')
|
||||||
visible_tags = fields.ObjectField(
|
visible_tags = fields.ObjectField(
|
||||||
properties={
|
properties={
|
||||||
'id': fields.IntegerField(attr='id'),
|
'id': fields.IntegerField(attr='id'),
|
||||||
|
|
@ -124,6 +148,7 @@ class EstablishmentDocument(Document):
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
favorites_for_users = fields.ListField(field=fields.IntegerField())
|
favorites_for_users = fields.ListField(field=fields.IntegerField())
|
||||||
|
tz = fields.KeywordField(attr='timezone_as_str')
|
||||||
|
|
||||||
class Django:
|
class Django:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,37 @@ class CustomGeoSpatialFilteringFilterBackend(GeoSpatialFilteringFilterBackend):
|
||||||
"""Automatically adds centering and sorting within bounding box."""
|
"""Automatically adds centering and sorting within bounding box."""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calculate_center(a, b):
|
def calculate_center(first, second):
|
||||||
return (a[0] + b[0]) / 2, (a[1] + b[1]) / 2
|
if second[1] < 0 < first[1]:
|
||||||
|
reverse_first, reverse_second = 180 - abs(first[1]), 180 - abs(second[1])
|
||||||
|
diff = (reverse_first + reverse_second) / 2
|
||||||
|
|
||||||
|
if reverse_first < reverse_second:
|
||||||
|
result_part = -180 + (180 + second[1] - diff)
|
||||||
|
|
||||||
|
else:
|
||||||
|
result_part = 180 - (180 - first[1] - diff)
|
||||||
|
|
||||||
|
elif second[1] < 0 > first[1]:
|
||||||
|
diff = abs(abs(second[1]) - abs(first[1]))
|
||||||
|
|
||||||
|
if diff > 90:
|
||||||
|
reverse_first, reverse_second = 180 - abs(first[1]), 180 - abs(second[1])
|
||||||
|
result_part = (reverse_first + reverse_second) / 2
|
||||||
|
|
||||||
|
else:
|
||||||
|
result_part = (first[1] + second[1]) / 2
|
||||||
|
|
||||||
|
else:
|
||||||
|
result_part = (first[1] + second[1]) / 2
|
||||||
|
|
||||||
|
return (first[0] + second[0]) / 2, result_part
|
||||||
|
|
||||||
def filter_queryset(self, request, queryset, view):
|
def filter_queryset(self, request, queryset, view):
|
||||||
ret = super().filter_queryset(request, queryset, view)
|
ret = super().filter_queryset(request, queryset, view)
|
||||||
bb = request.query_params.get('location__geo_bounding_box')
|
bb = request.query_params.get('location__geo_bounding_box')
|
||||||
if bb:
|
if bb:
|
||||||
center = self.calculate_center(*map(lambda p: list(map(lambda x: float(x),p.split(','))), bb.split('__')))
|
center = self.calculate_center(*map(lambda point: list(map(float, point.split(','))), bb.split('__')))
|
||||||
request.GET._mutable = True
|
request.GET._mutable = True
|
||||||
request.query_params.update({
|
request.query_params.update({
|
||||||
'ordering': f'location__{center[0]}__{center[1]}__km'
|
'ordering': f'location__{center[0]}__{center[1]}__km'
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,9 @@ class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer):
|
||||||
establishment_subtypes = EstablishmentTypeSerializer(many=True)
|
establishment_subtypes = EstablishmentTypeSerializer(many=True)
|
||||||
address = AddressDocumentSerializer(allow_null=True)
|
address = AddressDocumentSerializer(allow_null=True)
|
||||||
tags = TagsDocumentSerializer(many=True, source='visible_tags')
|
tags = TagsDocumentSerializer(many=True, source='visible_tags')
|
||||||
|
restaurant_category = TagsDocumentSerializer(many=True, allow_null=True)
|
||||||
|
restaurant_cuisine = TagsDocumentSerializer(many=True, allow_null=True)
|
||||||
|
artisan_category = TagsDocumentSerializer(many=True, allow_null=True)
|
||||||
schedule = ScheduleDocumentSerializer(many=True, allow_null=True)
|
schedule = ScheduleDocumentSerializer(many=True, allow_null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
@ -247,10 +250,14 @@ class EstablishmentDocumentSerializer(InFavoritesMixin, DocumentSerializer):
|
||||||
'preview_image',
|
'preview_image',
|
||||||
'address',
|
'address',
|
||||||
'tags',
|
'tags',
|
||||||
|
'restaurant_category',
|
||||||
|
'restaurant_cuisine',
|
||||||
|
'artisan_category',
|
||||||
'schedule',
|
'schedule',
|
||||||
'works_noon',
|
'works_noon',
|
||||||
'works_evening',
|
'works_evening',
|
||||||
'works_at_weekday',
|
'works_at_weekday',
|
||||||
|
'tz',
|
||||||
# 'works_now',
|
# 'works_now',
|
||||||
# 'collections',
|
# 'collections',
|
||||||
# 'establishment_type',
|
# 'establishment_type',
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,10 @@ class TagsFilterSet(TagsBaseFilterSet):
|
||||||
|
|
||||||
def by_establishment_type(self, queryset, name, value):
|
def by_establishment_type(self, queryset, name, value):
|
||||||
if value == EstablishmentType.ARTISAN:
|
if value == EstablishmentType.ARTISAN:
|
||||||
return models.Tag.objects.by_category_index_name('shop_category')[0:8]
|
qs = models.Tag.objects.by_category_index_name('shop_category')
|
||||||
|
if self.request.country_code and self.request.country_code not in settings.INTERNATIONAL_COUNTRY_CODES:
|
||||||
|
qs = qs.filter(establishments__address__city__country__code=self.request.country_code).distinct('id')
|
||||||
|
return qs.exclude(establishments__isnull=True)[0:8]
|
||||||
return queryset.by_establishment_type(value)
|
return queryset.by_establishment_type(value)
|
||||||
|
|
||||||
# TMP TODO remove it later
|
# TMP TODO remove it later
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ class EstablishmentSerializer(serializers.ModelSerializer):
|
||||||
weekdays = {
|
weekdays = {
|
||||||
'su': Timetable.SUNDAY,
|
'su': Timetable.SUNDAY,
|
||||||
'mo': Timetable.MONDAY,
|
'mo': Timetable.MONDAY,
|
||||||
'tu': Timetable.THURSDAY,
|
'tu': Timetable.TUESDAY,
|
||||||
'we': Timetable.WEDNESDAY,
|
'we': Timetable.WEDNESDAY,
|
||||||
'th': Timetable.THURSDAY,
|
'th': Timetable.THURSDAY,
|
||||||
'fr': Timetable.FRIDAY,
|
'fr': Timetable.FRIDAY,
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,12 @@ from tag.models import Tag
|
||||||
from transfer.models import PageMetadata
|
from transfer.models import PageMetadata
|
||||||
from utils.legacy_parser import parse_legacy_news_content
|
from utils.legacy_parser import parse_legacy_news_content
|
||||||
from utils.slug_generator import generate_unique_slug
|
from utils.slug_generator import generate_unique_slug
|
||||||
|
from account.models import User
|
||||||
|
|
||||||
|
|
||||||
class NewsSerializer(serializers.Serializer):
|
class NewsSerializer(serializers.Serializer):
|
||||||
id = serializers.IntegerField()
|
id = serializers.IntegerField()
|
||||||
|
account_id = serializers.IntegerField(allow_null=True)
|
||||||
tag_cat_id = serializers.IntegerField()
|
tag_cat_id = serializers.IntegerField()
|
||||||
news_type_id = serializers.IntegerField()
|
news_type_id = serializers.IntegerField()
|
||||||
news_title = serializers.CharField()
|
news_title = serializers.CharField()
|
||||||
|
|
@ -39,6 +41,8 @@ class NewsSerializer(serializers.Serializer):
|
||||||
'state': self.get_state(validated_data),
|
'state': self.get_state(validated_data),
|
||||||
'template': self.get_template(validated_data),
|
'template': self.get_template(validated_data),
|
||||||
'country': self.get_country(validated_data),
|
'country': self.get_country(validated_data),
|
||||||
|
'created_by': self.get_account(validated_data),
|
||||||
|
'modified_by': self.get_account(validated_data),
|
||||||
}
|
}
|
||||||
obj = News.objects.create(**payload)
|
obj = News.objects.create(**payload)
|
||||||
|
|
||||||
|
|
@ -126,3 +130,8 @@ class NewsSerializer(serializers.Serializer):
|
||||||
else:
|
else:
|
||||||
content = {data['locale']: data['title']}
|
content = {data['locale']: data['title']}
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_account(data):
|
||||||
|
"""Get account"""
|
||||||
|
return User.objects.filter(old_id=data['account_id']).first()
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ services:
|
||||||
mysql_db:
|
mysql_db:
|
||||||
image: mysql:5.7
|
image: mysql:5.7
|
||||||
ports:
|
ports:
|
||||||
- "3306:3306"
|
- "3316:3306"
|
||||||
environment:
|
environment:
|
||||||
MYSQL_DATABASE: dev
|
MYSQL_DATABASE: dev
|
||||||
MYSQL_USER: dev
|
MYSQL_USER: dev
|
||||||
|
|
|
||||||
|
|
@ -99,3 +99,6 @@ TESTING = sys.argv[1:2] == ['test']
|
||||||
if TESTING:
|
if TESTING:
|
||||||
ELASTICSEARCH_INDEX_NAMES = {}
|
ELASTICSEARCH_INDEX_NAMES = {}
|
||||||
ELASTICSEARCH_DSL_AUTOSYNC = False
|
ELASTICSEARCH_DSL_AUTOSYNC = False
|
||||||
|
|
||||||
|
# INSTALLED APPS
|
||||||
|
INSTALLED_APPS.append('transfer.apps.TransferConfig')
|
||||||
Loading…
Reference in New Issue
Block a user