From fd926ee48657685b9efd5909232a1292be471635 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Mon, 4 Nov 2019 17:15:33 +0300 Subject: [PATCH 01/41] old id for prod --- project/settings/production.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/settings/production.py b/project/settings/production.py index 4f9e90b7..0ac6dfca 100644 --- a/project/settings/production.py +++ b/project/settings/production.py @@ -39,7 +39,7 @@ sentry_sdk.init( # TMP ( TODO remove it later) # Временный хардкод для демонстрации 4 ноября, потом удалить! -HARDCODED_INTERNATIONAL_NEWS_IDS = [8, 9, 10, 11, 15, 17] +HARDCODED_INTERNATIONAL_NEWS_IDS = [1460, 1471, 1482, 1484, 1611, 1612] # Database # https://docs.djangoproject.com/en/2.2/ref/settings/#databases From f1d22c23927e849b12be846d283169f2354ea0a8 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Mon, 4 Nov 2019 17:32:22 +0300 Subject: [PATCH 02/41] redis for prod --- project/settings/production.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/settings/production.py b/project/settings/production.py index 0ac6dfca..62f77793 100644 --- a/project/settings/production.py +++ b/project/settings/production.py @@ -55,7 +55,7 @@ DATABASES = { }, } -BROKER_URL = 'redis://localhost:6379/1' +BROKER_URL = 'redis://redis:6379/1' CELERY_RESULT_BACKEND = BROKER_URL CELERY_BROKER_URL = BROKER_URL From 9d087b53ee7fd6ed17b33eefd06475162fd5d143 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 03/41] Hardcode for presentation --- apps/main/views/common.py | 4 ++++ apps/news/views.py | 6 +++++- project/settings/base.py | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/main/views/common.py b/apps/main/views/common.py index d509f80e..15f89510 100644 --- a/apps/main/views/common.py +++ b/apps/main/views/common.py @@ -1,5 +1,6 @@ """Main app views.""" from django.http import Http404 +from django.conf import settings from rest_framework import generics, permissions from rest_framework.response import Response @@ -69,6 +70,9 @@ class CarouselListView(generics.ListAPIView): def get_queryset(self): country_code = self.request.country_code + if hasattr(settings, 'CAROUSEL_ITEMS') and country_code in ['www', 'main']: + qs = models.Carousel.objects.filter(id__in=settings.CAROUSEL_ITEMS) + return qs qs = models.Carousel.objects.is_parsed().active() if country_code: qs = qs.by_country_code(country_code) diff --git a/apps/news/views.py b/apps/news/views.py index 990665dd..04fa29a1 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -32,7 +32,7 @@ class NewsMixinView: # (по договорённости с заказчиком на демонстрации 4 ноября # здесь будет 6 фиксированных новостей) # TODO replace this stub with actual logic - if hasattr(settings, 'HARDCODED_INTERNATIONAL_NEWS_IDS'): + if hasattr(settings, 'HARDCODED_INTERNATIONAL_NEWS_IDS') and kwargs.get('hardcoded_only', False): if country_code and country_code != 'www' and country_code != 'main': qs = qs.by_country_code(country_code) else: @@ -51,6 +51,10 @@ class NewsListView(NewsMixinView, generics.ListAPIView): serializer_class = serializers.NewsListSerializer filter_class = filters.NewsListFilterSet + def get_queryset(self, *args, **kwargs): + kwargs.update({'hardcoded_only': True}) + super().get_queryset(*args, **kwargs) + class NewsDetailView(NewsMixinView, generics.RetrieveAPIView): """News detail view.""" diff --git a/project/settings/base.py b/project/settings/base.py index 686f246e..839ee9e0 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -493,5 +493,6 @@ FALLBACK_LOCALE = 'en-GB' # TMP TODO remove it later # Временный хардкод для демонстрации 4 ноября, потом удалить! +CAROUSEL_ITEMS = [230, 231, 232] ESTABLISHMENT_CHOSEN_TAGS = ['gastronomic', 'en_vogue', 'terrace', 'streetfood', 'business', 'bar_cocktail', 'brunch', 'pop'] NEWS_CHOSEN_TAGS = ['eat', 'drink', 'cook', 'style', 'international', 'event', 'partnership'] \ No newline at end of file From f9a1747143b10d8cef3c4e8cae4a6b435159c5fb Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Mon, 4 Nov 2019 18:38:56 +0300 Subject: [PATCH 04/41] change version kombu --- requirements/base.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements/base.txt b/requirements/base.txt index a6a007bd..7ae1fe1f 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -48,4 +48,6 @@ PyYAML==5.1.2 # temp solution redis==3.2.0 amqp>=2.4.0 + +kombu==4.5.0 celery==4.3.0rc2 From 210e4d39f15aff621e6e002284d37bf7b9caac90 Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Mon, 4 Nov 2019 18:58:21 +0300 Subject: [PATCH 05/41] disabled debug --- project/settings/production.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/project/settings/production.py b/project/settings/production.py index 62f77793..49e972d6 100644 --- a/project/settings/production.py +++ b/project/settings/production.py @@ -4,6 +4,9 @@ from .amazon_s3 import * import sentry_sdk from sentry_sdk.integrations.django import DjangoIntegration +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = False + ALLOWED_HOSTS = ['*.next.gaultmillau.com', 'api.gaultmillau.com'] CSRF_TRUSTED_ORIGINS = ['.next.gaultmillau.com', ] From c5e96a7ad86449cb63949c816c43ce53a891265d Mon Sep 17 00:00:00 2001 From: Dmitriy Kuzmenko Date: Mon, 4 Nov 2019 20:33:35 +0300 Subject: [PATCH 06/41] fix retrieve --- apps/news/views.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/news/views.py b/apps/news/views.py index 04fa29a1..e91003e8 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -62,9 +62,10 @@ class NewsDetailView(NewsMixinView, generics.RetrieveAPIView): lookup_field = 'slug' serializer_class = serializers.NewsDetailWebSerializer + queryset = models.News.objects.all() + def get_queryset(self): - """Override get_queryset method.""" - return super().get_queryset().with_extended_related() + return self.queryset class NewsTypeListView(generics.ListAPIView): From f52847a71a891a53b673f9dd7ef4509e1a0760d7 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 07/41] Remove all crunches from projects --- apps/main/views/common.py | 3 --- apps/news/views.py | 20 -------------------- apps/tag/filters.py | 15 --------------- apps/tag/views.py | 17 ----------------- project/settings/base.py | 6 ------ project/settings/development.py | 4 ---- project/settings/production.py | 4 ---- project/settings/stage.py | 5 ----- 8 files changed, 74 deletions(-) diff --git a/apps/main/views/common.py b/apps/main/views/common.py index 15f89510..0c2ef6d4 100644 --- a/apps/main/views/common.py +++ b/apps/main/views/common.py @@ -70,9 +70,6 @@ class CarouselListView(generics.ListAPIView): def get_queryset(self): country_code = self.request.country_code - if hasattr(settings, 'CAROUSEL_ITEMS') and country_code in ['www', 'main']: - qs = models.Carousel.objects.filter(id__in=settings.CAROUSEL_ITEMS) - return qs qs = models.Carousel.objects.is_parsed().active() if country_code: qs = qs.by_country_code(country_code) diff --git a/apps/news/views.py b/apps/news/views.py index e91003e8..b6016446 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -18,7 +18,6 @@ class NewsMixinView: serializer_class = serializers.NewsBaseSerializer def get_queryset(self, *args, **kwargs): - from django.conf import settings """Override get_queryset method.""" qs = models.News.objects.published() \ @@ -26,21 +25,6 @@ class NewsMixinView: .order_by('-is_highlighted', '-created') country_code = self.request.country_code if country_code: - - # temp code - # Temporary stub for international news logic - # (по договорённости с заказчиком на демонстрации 4 ноября - # здесь будет 6 фиксированных новостей) - # TODO replace this stub with actual logic - if hasattr(settings, 'HARDCODED_INTERNATIONAL_NEWS_IDS') and kwargs.get('hardcoded_only', False): - if country_code and country_code != 'www' and country_code != 'main': - qs = qs.by_country_code(country_code) - else: - qs = models.News.objects.filter( - old_id__in=settings.HARDCODED_INTERNATIONAL_NEWS_IDS) - return qs - # temp code - qs = qs.by_country_code(country_code) return qs @@ -51,10 +35,6 @@ class NewsListView(NewsMixinView, generics.ListAPIView): serializer_class = serializers.NewsListSerializer filter_class = filters.NewsListFilterSet - def get_queryset(self, *args, **kwargs): - kwargs.update({'hardcoded_only': True}) - super().get_queryset(*args, **kwargs) - class NewsDetailView(NewsMixinView, generics.RetrieveAPIView): """News detail view.""" diff --git a/apps/tag/filters.py b/apps/tag/filters.py index 2dc3a775..e8263e0d 100644 --- a/apps/tag/filters.py +++ b/apps/tag/filters.py @@ -54,18 +54,3 @@ class TagsFilterSet(TagsBaseFilterSet): model = models.Tag fields = ('type',) - - - # TMP TODO remove it later - # Временный хардкод для демонстрации 4 ноября, потом удалить! - def filter_by_type(self, queryset, name, value): - """ Overrides base filter. Temporary decision""" - if not (settings.NEWS_CHOSEN_TAGS and settings.ESTABLISHMENT_CHOSEN_TAGS): - return super().filter_by_type(queryset, name, value) - queryset = models.Tag.objects - if self.NEWS in value: - queryset = queryset.for_news().filter(value__in=settings.NEWS_CHOSEN_TAGS).distinct('value') - if self.ESTABLISHMENT in value: - queryset = queryset.for_establishments().filter(value__in=settings.ESTABLISHMENT_CHOSEN_TAGS).distinct( - 'value') - return queryset \ No newline at end of file diff --git a/apps/tag/views.py b/apps/tag/views.py index a4beaaa0..c55834e0 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -23,23 +23,6 @@ class ChosenTagsView(generics.ListAPIView, viewsets.GenericViewSet): .filter(id__in=result_tags_ids) \ .order_by_priority() - def list(self, request, *args, **kwargs): - # TMP TODO remove it later - # Временный хардкод для демонстрации 4 ноября, потом удалить! - queryset = self.filter_queryset(self.get_queryset()) - - page = self.paginate_queryset(queryset) - if page is not None: - serializer = self.get_serializer(page, many=True) - return self.get_paginated_response(serializer.data) - - serializer = self.get_serializer(queryset, many=True) - result_list = serializer.data - if request.query_params.get('type') and (settings.ESTABLISHMENT_CHOSEN_TAGS or settings.NEWS_CHOSEN_TAGS): - ordered_list = settings.ESTABLISHMENT_CHOSEN_TAGS if request.query_params.get('type') == 'establishment' else settings.NEWS_CHOSEN_TAGS - result_list = sorted(result_list, key=lambda x: ordered_list.index(x['index_name'])) - return Response(result_list) - # User`s views & viewsets class TagCategoryViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): diff --git a/project/settings/base.py b/project/settings/base.py index 839ee9e0..80baf04a 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -490,9 +490,3 @@ PHONENUMBER_DB_FORMAT = 'NATIONAL' PHONENUMBER_DEFAULT_REGION = "FR" FALLBACK_LOCALE = 'en-GB' - -# TMP TODO remove it later -# Временный хардкод для демонстрации 4 ноября, потом удалить! -CAROUSEL_ITEMS = [230, 231, 232] -ESTABLISHMENT_CHOSEN_TAGS = ['gastronomic', 'en_vogue', 'terrace', 'streetfood', 'business', 'bar_cocktail', 'brunch', 'pop'] -NEWS_CHOSEN_TAGS = ['eat', 'drink', 'cook', 'style', 'international', 'event', 'partnership'] \ No newline at end of file diff --git a/project/settings/development.py b/project/settings/development.py index c6f80f9e..16297f40 100644 --- a/project/settings/development.py +++ b/project/settings/development.py @@ -38,10 +38,6 @@ sentry_sdk.init( integrations=[DjangoIntegration()] ) -# TMP ( TODO remove it later) -# Временный хардкод для демонстрации 4 ноября, потом удалить! -HARDCODED_INTERNATIONAL_NEWS_IDS = [1460, 1471, 1482, 1484, 1611, 1612] - # Database # https://docs.djangoproject.com/en/2.2/ref/settings/#databases diff --git a/project/settings/production.py b/project/settings/production.py index 49e972d6..a531a2ae 100644 --- a/project/settings/production.py +++ b/project/settings/production.py @@ -40,10 +40,6 @@ sentry_sdk.init( integrations=[DjangoIntegration()] ) -# TMP ( TODO remove it later) -# Временный хардкод для демонстрации 4 ноября, потом удалить! -HARDCODED_INTERNATIONAL_NEWS_IDS = [1460, 1471, 1482, 1484, 1611, 1612] - # Database # https://docs.djangoproject.com/en/2.2/ref/settings/#databases diff --git a/project/settings/stage.py b/project/settings/stage.py index b70563c9..49a7ae0f 100644 --- a/project/settings/stage.py +++ b/project/settings/stage.py @@ -26,8 +26,3 @@ ELASTICSEARCH_INDEX_NAMES = { # 'search_indexes.documents.news': 'stage_news', #temporarily disabled 'search_indexes.documents.establishment': 'stage_establishment', } - - -# TMP ( TODO remove it later) -# Временный хардкод для демонстрации 4 ноября, потом удалить! -HARDCODED_INTERNATIONAL_NEWS_IDS = [1460, 1471, 1482, 1484, 1611, 1612] \ No newline at end of file From 06f5a551b871e40fd789cbdc7b4dcc1b75b977c9 Mon Sep 17 00:00:00 2001 From: michail Date: Tue, 5 Nov 2019 16:45:43 +0500 Subject: [PATCH 08/41] additions for migration of comments --- apps/comment/transfer_data.py | 4 +-- apps/transfer/management/commands/transfer.py | 1 + apps/transfer/serializers/comments.py | 25 +++++++++++++++++-- project/settings/base.py | 2 +- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/apps/comment/transfer_data.py b/apps/comment/transfer_data.py index 3a291b86..a9ac4f35 100644 --- a/apps/comment/transfer_data.py +++ b/apps/comment/transfer_data.py @@ -15,7 +15,7 @@ def transfer_comments(): data_types = { - "tmp": [ - # transfer_comments + "comment": [ + transfer_comments ] } diff --git a/apps/transfer/management/commands/transfer.py b/apps/transfer/management/commands/transfer.py index 06782c9b..e75deb32 100644 --- a/apps/transfer/management/commands/transfer.py +++ b/apps/transfer/management/commands/transfer.py @@ -27,6 +27,7 @@ class Command(BaseCommand): LONG_DATA_TYPES = [ 'update_country_flag', + 'comment' ] def handle(self, *args, **options): diff --git a/apps/transfer/serializers/comments.py b/apps/transfer/serializers/comments.py index 584370e6..14ad70e3 100644 --- a/apps/transfer/serializers/comments.py +++ b/apps/transfer/serializers/comments.py @@ -1,6 +1,7 @@ from rest_framework import serializers from comment.models import Comment, User from establishment.models import Establishment +from location.models import Country class CommentSerializer(serializers.ModelSerializer): @@ -28,8 +29,16 @@ class CommentSerializer(serializers.ModelSerializer): data = self.set_mark(data) data = self.set_establishment(data) data = self.set_account(data) + data = self.set_country(data) + return data + def create(self, validated_data): + try: + return Comment.objects.create(**validated_data) + except Exception as e: + raise ValueError(f"Error creating comment with {validated_data}: {e}") + def set_text(self, data): data['text'] = data.pop('comment') return data @@ -41,7 +50,7 @@ class CommentSerializer(serializers.ModelSerializer): def set_account(self, data): try: - data['account'] = User.objects.filter(old_id=data['account_id']).first() + data['user'] = User.objects.filter(old_id=data['account_id']).first() except User.DoesNotExist as e: raise ValueError(f"User account not found with {data}: {e}") @@ -51,9 +60,10 @@ class CommentSerializer(serializers.ModelSerializer): def set_establishment(self, data): try: - data['establishment'] = Establishment.objects.filter(old_id=data['account_id']).first() + data['content_object'] = Establishment.objects.filter(old_id=data['establishment_id']).first() except Establishment.DoesNotExist as e: raise ValueError(f"Establishment not found with {data}: {e}") + # print(f"Establishment not found with {data}: {e}") del(data['establishment_id']) @@ -62,3 +72,14 @@ class CommentSerializer(serializers.ModelSerializer): def set_old_id(self, data): data['old_id'] = data.pop("id") return data + + def set_country(self, data): + locale = data.pop("locale") + country_code = locale[:locale.index("-")] if len(locale) > 2 else locale + + try: + data['country'] = Country.objects.filter(code=country_code).first() + except Country.DoesNotExist as e: + raise ValueError(f"Country not found with {data}: {e}") + + return data \ No newline at end of file diff --git a/project/settings/base.py b/project/settings/base.py index 839ee9e0..e2abf5d6 100644 --- a/project/settings/base.py +++ b/project/settings/base.py @@ -74,7 +74,7 @@ PROJECT_APPS = [ 'comment.apps.CommentConfig', 'favorites.apps.FavoritesConfig', 'rating.apps.RatingConfig', - # 'transfer.apps.TransferConfig', + 'transfer.apps.TransferConfig', 'tag.apps.TagConfig', 'product.apps.ProductConfig', ] From 346f126dbbcc49f99e8a6d991a51f1d84bee6b8c Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Tue, 5 Nov 2019 14:48:25 +0300 Subject: [PATCH 09/41] Added news filter (by country). --- apps/search_indexes/views.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py index 29905125..25e7812b 100644 --- a/apps/search_indexes/views.py +++ b/apps/search_indexes/views.py @@ -46,6 +46,12 @@ class NewsDocumentViewSet(BaseDocumentViewSet): ] }, 'slug': 'slug', + 'country_id': { + 'field': 'country.id' + }, + 'country': { + 'field': 'country.code' + }, } From e7143f73c3b5019b481ff2d4977cdf2958d1eafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Tue, 5 Nov 2019 14:59:32 +0300 Subject: [PATCH 10/41] Add positions --- .../management/commands/add_position.py | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 apps/establishment/management/commands/add_position.py diff --git a/apps/establishment/management/commands/add_position.py b/apps/establishment/management/commands/add_position.py new file mode 100644 index 00000000..810913dd --- /dev/null +++ b/apps/establishment/management/commands/add_position.py @@ -0,0 +1,36 @@ +from django.core.management.base import BaseCommand +from django.db import connection, connections +from collections import namedtuple +from establishment.models import Position + + +def namedtuplefetchall(cursor): + "Return all rows from a cursor as a namedtuple" + desc = cursor.description + nt_result = namedtuple('Result', [col[0] for col in desc]) + return [nt_result(*row) for row in cursor.fetchall()] + + +class Command(BaseCommand): + help = 'Add position from old db to new db' + + def position_sql(self): + with connections['legacy'].cursor() as cursor: + cursor.execute(''' + select + DISTINCT a.`role` as position_name + from affiliations as a + ''') + return namedtuplefetchall(cursor) + + def handle(self, *args, **kwargs): + + objects = [] + for p in self.position_sql(): + count = Position.objects.filter(name={"en-GB": p.position_name}).count() + if count == 0: + objects.append(Position(name={"en-GB": p.position_name})) + print(p.position_name) + + p = Position.objects.bulk_create(objects) + self.stdout.write(self.style.WARNING(f'Created positions objects.')) From 83bab7f383050d3abb0108528b665f1d8048568d Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Tue, 5 Nov 2019 15:59:28 +0300 Subject: [PATCH 11/41] remove hardcoded news --- apps/news/views.py | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/apps/news/views.py b/apps/news/views.py index e91003e8..c65c5297 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -18,29 +18,12 @@ class NewsMixinView: serializer_class = serializers.NewsBaseSerializer def get_queryset(self, *args, **kwargs): - from django.conf import settings """Override get_queryset method.""" - qs = models.News.objects.published() \ .with_base_related() \ .order_by('-is_highlighted', '-created') country_code = self.request.country_code if country_code: - - # temp code - # Temporary stub for international news logic - # (по договорённости с заказчиком на демонстрации 4 ноября - # здесь будет 6 фиксированных новостей) - # TODO replace this stub with actual logic - if hasattr(settings, 'HARDCODED_INTERNATIONAL_NEWS_IDS') and kwargs.get('hardcoded_only', False): - if country_code and country_code != 'www' and country_code != 'main': - qs = qs.by_country_code(country_code) - else: - qs = models.News.objects.filter( - old_id__in=settings.HARDCODED_INTERNATIONAL_NEWS_IDS) - return qs - # temp code - qs = qs.by_country_code(country_code) return qs @@ -51,10 +34,6 @@ class NewsListView(NewsMixinView, generics.ListAPIView): serializer_class = serializers.NewsListSerializer filter_class = filters.NewsListFilterSet - def get_queryset(self, *args, **kwargs): - kwargs.update({'hardcoded_only': True}) - super().get_queryset(*args, **kwargs) - class NewsDetailView(NewsMixinView, generics.RetrieveAPIView): """News detail view.""" From 568ec84da03f4c0cdfb07fe4526b6dae40874390 Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Tue, 5 Nov 2019 16:20:24 +0300 Subject: [PATCH 12/41] Added filter class to EstalibshmentListCreateView --- apps/establishment/views/back.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/establishment/views/back.py b/apps/establishment/views/back.py index e490d576..f6d4d63a 100644 --- a/apps/establishment/views/back.py +++ b/apps/establishment/views/back.py @@ -3,7 +3,7 @@ from django.shortcuts import get_object_or_404 from rest_framework import generics from utils.permissions import IsCountryAdmin, IsEstablishmentManager -from establishment import models, serializers +from establishment import filters, models, serializers from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer @@ -17,9 +17,11 @@ class EstablishmentMixinViews: class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAPIView): """Establishment list/create view.""" + + filter_class = filters.EstablishmentFilter + permission_classes = [IsCountryAdmin | IsEstablishmentManager] queryset = models.Establishment.objects.all() serializer_class = serializers.EstablishmentListCreateSerializer - permission_classes = [IsCountryAdmin|IsEstablishmentManager] class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView): From ea1ddfa320a899d30ef41225f5b97ebb29f1c08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Tue, 5 Nov 2019 16:29:27 +0300 Subject: [PATCH 13/41] Add employee --- .../management/commands/add_employee.py | 39 +++++++++++++++++++ .../management/commands/add_position.py | 3 +- .../migrations/0055_employee_old_id.py | 18 +++++++++ apps/establishment/models.py | 2 + 4 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 apps/establishment/management/commands/add_employee.py create mode 100644 apps/establishment/migrations/0055_employee_old_id.py diff --git a/apps/establishment/management/commands/add_employee.py b/apps/establishment/management/commands/add_employee.py new file mode 100644 index 00000000..49eaa056 --- /dev/null +++ b/apps/establishment/management/commands/add_employee.py @@ -0,0 +1,39 @@ +from django.core.management.base import BaseCommand +from django.db import connections +from establishment.management.commands.add_position import namedtuplefetchall +from establishment.models import Employee + + +class Command(BaseCommand): + + help = 'Add employee from old db to new db' + + def employees_sql(self): + with connections['legacy'].cursor() as cursor: + cursor.execute(''' + select t.profile_id, t.name + from + ( + select + DISTINCT + a.profile_id, + trim(CONCAT(p.firstname, ' ', p.lastname, ' ', + p.email,'') + ) as name + from affiliations as a + join profiles p on p.id = a.profile_id + ) t + where t.name is not null + ''') + return namedtuplefetchall(cursor) + + def handle(self, *args, **options): + objects = [] + for e in self.employees_sql(): + count = Employee.objects.filter(old_id=e.profile_id).count() + count += Employee.objects.filter(name=e.name).count() + if count == 0: + objects.append(Employee(name=e.name, old_id=e.profile_id)) + print(e.name) + empls = Employee.objects.bulk_create(objects) + self.stdout.write(self.style.WARNING(f'Created employee objects.')) diff --git a/apps/establishment/management/commands/add_position.py b/apps/establishment/management/commands/add_position.py index 810913dd..0a456a69 100644 --- a/apps/establishment/management/commands/add_position.py +++ b/apps/establishment/management/commands/add_position.py @@ -1,5 +1,5 @@ from django.core.management.base import BaseCommand -from django.db import connection, connections +from django.db import connections from collections import namedtuple from establishment.models import Position @@ -30,7 +30,6 @@ class Command(BaseCommand): count = Position.objects.filter(name={"en-GB": p.position_name}).count() if count == 0: objects.append(Position(name={"en-GB": p.position_name})) - print(p.position_name) p = Position.objects.bulk_create(objects) self.stdout.write(self.style.WARNING(f'Created positions objects.')) diff --git a/apps/establishment/migrations/0055_employee_old_id.py b/apps/establishment/migrations/0055_employee_old_id.py new file mode 100644 index 00000000..f13bff43 --- /dev/null +++ b/apps/establishment/migrations/0055_employee_old_id.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.4 on 2019-11-05 13:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0054_auto_20191103_2117'), + ] + + operations = [ + migrations.AddField( + model_name='employee', + name='old_id', + field=models.IntegerField(blank=True, null=True, verbose_name='Old id'), + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 8ea4601b..1c89fe9b 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -578,6 +578,8 @@ class Employee(BaseAttributes): awards = generic.GenericRelation(to='main.Award', related_query_name='employees') tags = models.ManyToManyField('tag.Tag', related_name='employees', verbose_name=_('Tags')) + # old_id = profile_id + old_id = models.IntegerField(verbose_name=_('Old id'), null=True, blank=True) class Meta: """Meta class.""" From 22982f33326495973cf42f7303d89424dcfded84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Tue, 5 Nov 2019 16:33:38 +0300 Subject: [PATCH 14/41] Add employee fix --- apps/establishment/management/commands/add_employee.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/establishment/management/commands/add_employee.py b/apps/establishment/management/commands/add_employee.py index 49eaa056..6fbf562f 100644 --- a/apps/establishment/management/commands/add_employee.py +++ b/apps/establishment/management/commands/add_employee.py @@ -2,7 +2,7 @@ from django.core.management.base import BaseCommand from django.db import connections from establishment.management.commands.add_position import namedtuplefetchall from establishment.models import Employee - +from django.db.models import Q class Command(BaseCommand): @@ -30,8 +30,7 @@ class Command(BaseCommand): def handle(self, *args, **options): objects = [] for e in self.employees_sql(): - count = Employee.objects.filter(old_id=e.profile_id).count() - count += Employee.objects.filter(name=e.name).count() + count = Employee.objects.filter(Q(old_id=e.profile_id) | Q(name=e.name)).count() if count == 0: objects.append(Employee(name=e.name, old_id=e.profile_id)) print(e.name) From 273478a7cb5570e13bf94456fc5e1f275dc4dcb7 Mon Sep 17 00:00:00 2001 From: evgeniy-st Date: Tue, 5 Nov 2019 16:57:07 +0300 Subject: [PATCH 15/41] add address to establishmentRUDSerializer --- apps/establishment/serializers/back.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py index f1fb40a5..a8db6000 100644 --- a/apps/establishment/serializers/back.py +++ b/apps/establishment/serializers/back.py @@ -73,7 +73,8 @@ class EstablishmentRUDSerializer(EstablishmentBaseSerializer): 'socials', 'image_url', # TODO: check in admin filters - 'is_publish' + 'is_publish', + 'address' ] From a60fb84bcbeaec9a3b0655c8f316518108b82ae4 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 16/41] Use not only closed_at / opening_at --- apps/establishment/models.py | 4 ++-- apps/timetable/models.py | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 8ea4601b..83950cbe 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -471,10 +471,10 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin): now_at_est_tz = datetime.now(tz=self.tz) current_week = now_at_est_tz.weekday() schedule_for_today = self.schedule.filter(weekday=current_week).first() - if schedule_for_today is None or schedule_for_today.closed_at is None or schedule_for_today.opening_at is None: + if schedule_for_today is None or schedule_for_today.opening_time is None or schedule_for_today.ending_time is None: return False time_at_est_tz = now_at_est_tz.time() - return schedule_for_today.closed_at > time_at_est_tz > schedule_for_today.opening_at + return schedule_for_today.ending_time > time_at_est_tz > schedule_for_today.opening_time @property def tags_indexing(self): diff --git a/apps/timetable/models.py b/apps/timetable/models.py index 35469c32..cf7f8d94 100644 --- a/apps/timetable/models.py +++ b/apps/timetable/models.py @@ -39,13 +39,21 @@ class Timetable(ProjectBaseMixin): def closed_at_str(self): return str(self.closed_at) if self.closed_at else None + @property + def opening_time(self): + return self.opening_at or self.lunch_start or self.dinner_start + + @property + def ending_time(self): + return self.closed_at or self.dinner_end or self.lunch_end + @property def works_at_noon(self): - return bool(self.closed_at and self.closed_at <= self.NOON) + return bool(self.opening_time and self.opening_time <= self.NOON) @property def works_at_afternoon(self): - return bool(self.closed_at and self.closed_at > self.NOON) + return bool(self.ending_time and self.ending_time > self.NOON) class Meta: """Meta class.""" From 6f4cd56fcdbdc298e2320a69ac0bbd04b9ac044a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Tue, 5 Nov 2019 17:28:13 +0300 Subject: [PATCH 17/41] Add establishment employee --- .../management/commands/add_empl_position.py | 56 +++++++++++++++++++ .../management/commands/add_employee.py | 2 +- .../migrations/0056_auto_20191105_1401.py | 19 +++++++ .../0057_establishmentemployee_old_id.py | 18 ++++++ apps/establishment/models.py | 5 +- 5 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 apps/establishment/management/commands/add_empl_position.py create mode 100644 apps/establishment/migrations/0056_auto_20191105_1401.py create mode 100644 apps/establishment/migrations/0057_establishmentemployee_old_id.py diff --git a/apps/establishment/management/commands/add_empl_position.py b/apps/establishment/management/commands/add_empl_position.py new file mode 100644 index 00000000..6686e5e3 --- /dev/null +++ b/apps/establishment/management/commands/add_empl_position.py @@ -0,0 +1,56 @@ +from django.core.management.base import BaseCommand +from django.db import connections +from establishment.management.commands.add_position import namedtuplefetchall +from establishment.models import Establishment, Position, Employee, EstablishmentEmployee + + +class Command(BaseCommand): + help = 'Add employee position from old db to new db' + + def empl_position_sql(self): + with connections['legacy'].cursor() as cursor: + cursor.execute(''' + select t.id, + t.profile_id, + t.establishment_id, + t.role, + t.start_date, + t.end_date + from + ( + select + DISTINCT + a.id, + a.profile_id, + a.establishment_id, + a.role, + a.start_date, + a.end_date, + trim(CONCAT(p.firstname, ' ', p.lastname, ' ', + p.email,'') + ) as name + from affiliations as a + join profiles p on p.id = a.profile_id + ) t + where t.name is not null + ''') + return namedtuplefetchall(cursor) + + def handle(self, *args, **options): + objects = [] + for e in self.empl_position_sql(): + pos = Position.objects.filter(name={"en-GB": e.role}).first() + empl = Employee.objects.filter(old_id=e.profile_id).first() + est = Establishment.objects.filter(old_id=e.establishment_id).first() + if pos and empl and est: + est_empl = EstablishmentEmployee( + from_date=e.start_date, to_date=e.end_date, + old_id=e.id + ) + est_empl.establishment = est + est_empl.employee = empl + est_empl.position = pos + objects.append(est_empl) + + ee = EstablishmentEmployee.objects.bulk_create(objects) + self.stdout.write(self.style.WARNING(f'Created establishment employee objects.')) diff --git a/apps/establishment/management/commands/add_employee.py b/apps/establishment/management/commands/add_employee.py index 6fbf562f..f01e6396 100644 --- a/apps/establishment/management/commands/add_employee.py +++ b/apps/establishment/management/commands/add_employee.py @@ -4,8 +4,8 @@ from establishment.management.commands.add_position import namedtuplefetchall from establishment.models import Employee from django.db.models import Q -class Command(BaseCommand): +class Command(BaseCommand): help = 'Add employee from old db to new db' def employees_sql(self): diff --git a/apps/establishment/migrations/0056_auto_20191105_1401.py b/apps/establishment/migrations/0056_auto_20191105_1401.py new file mode 100644 index 00000000..4b845dd7 --- /dev/null +++ b/apps/establishment/migrations/0056_auto_20191105_1401.py @@ -0,0 +1,19 @@ +# Generated by Django 2.2.4 on 2019-11-05 14:01 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0055_employee_old_id'), + ] + + operations = [ + migrations.AlterField( + model_name='establishmentemployee', + name='from_date', + field=models.DateTimeField(blank=True, default=django.utils.timezone.now, null=True, verbose_name='From date'), + ), + ] diff --git a/apps/establishment/migrations/0057_establishmentemployee_old_id.py b/apps/establishment/migrations/0057_establishmentemployee_old_id.py new file mode 100644 index 00000000..a1a66517 --- /dev/null +++ b/apps/establishment/migrations/0057_establishmentemployee_old_id.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.4 on 2019-11-05 14:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('establishment', '0056_auto_20191105_1401'), + ] + + operations = [ + migrations.AddField( + model_name='establishmentemployee', + name='old_id', + field=models.IntegerField(blank=True, null=True, verbose_name='Old id'), + ), + ] diff --git a/apps/establishment/models.py b/apps/establishment/models.py index 1c89fe9b..892c34a8 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -557,11 +557,14 @@ class EstablishmentEmployee(BaseAttributes): 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')) + from_date = models.DateTimeField(default=timezone.now, verbose_name=_('From date'), + null=True, blank=True) 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')) + # old_id = affiliations_id + old_id = models.IntegerField(verbose_name=_('Old id'), null=True, blank=True) objects = EstablishmentEmployeeQuerySet.as_manager() From 545e9a249b21a45d43570af9049b20fc69fe5d7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Tue, 5 Nov 2019 17:32:18 +0300 Subject: [PATCH 18/41] Fix help --- apps/establishment/management/commands/add_empl_position.py | 3 ++- apps/establishment/management/commands/add_employee.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/establishment/management/commands/add_empl_position.py b/apps/establishment/management/commands/add_empl_position.py index 6686e5e3..358c340b 100644 --- a/apps/establishment/management/commands/add_empl_position.py +++ b/apps/establishment/management/commands/add_empl_position.py @@ -5,7 +5,8 @@ from establishment.models import Establishment, Position, Employee, Establishmen class Command(BaseCommand): - help = 'Add employee position from old db to new db' + help = '''Add employee position from old db to new db. + Run after add_position and add_employee!''' def empl_position_sql(self): with connections['legacy'].cursor() as cursor: diff --git a/apps/establishment/management/commands/add_employee.py b/apps/establishment/management/commands/add_employee.py index f01e6396..4abf588a 100644 --- a/apps/establishment/management/commands/add_employee.py +++ b/apps/establishment/management/commands/add_employee.py @@ -6,7 +6,7 @@ from django.db.models import Q class Command(BaseCommand): - help = 'Add employee from old db to new db' + help = 'Add employee from old db to new db.' def employees_sql(self): with connections['legacy'].cursor() as cursor: From be48bff5aeb4db0c098a8f94477bbe6503c1dc8d Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 19/41] Send confirmation to new email --- apps/account/models.py | 9 +++++---- apps/account/serializers/common.py | 6 ++++-- apps/account/tasks.py | 9 +++++---- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/apps/account/models.py b/apps/account/models.py index 3eb07722..5d5005e8 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -158,19 +158,20 @@ class User(AbstractUser): self.is_active = True self.save() - def get_body_email_message(self, subject: str, message: str): + def get_body_email_message(self, subject: str, message: str, emails=None): """Prepare the body of the email message""" return { 'subject': subject, 'message': str(message), 'from_email': settings.EMAIL_HOST_USER, - 'recipient_list': [self.email, ] + 'recipient_list': emails if emails else [self.email, ] } - def send_email(self, subject: str, message: str): + def send_email(self, subject: str, message: str, emails=None): """Send an email to reset user password""" send_mail(**self.get_body_email_message(subject=subject, - message=message)) + message=message, + emails=emails)) @property def confirm_email_token(self): diff --git a/apps/account/serializers/common.py b/apps/account/serializers/common.py index d68cfe56..20016297 100644 --- a/apps/account/serializers/common.py +++ b/apps/account/serializers/common.py @@ -72,11 +72,13 @@ class UserSerializer(serializers.ModelSerializer): if settings.USE_CELERY: tasks.change_email_address.delay( user_id=instance.id, - country_code=self.context.get('request').country_code) + country_code=self.context.get('request').country_code, + emails=[validated_data['email'],]) else: tasks.change_email_address( user_id=instance.id, - country_code=self.context.get('request').country_code) + country_code=self.context.get('request').country_code, + emails=[validated_data['email'],]) return instance diff --git a/apps/account/tasks.py b/apps/account/tasks.py index d9fa7bb7..21b22320 100644 --- a/apps/account/tasks.py +++ b/apps/account/tasks.py @@ -10,11 +10,12 @@ from account.models import User logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) -def send_email(user_id: int, subject: str, message_prop: str, country_code: str): +def send_email(user_id: int, subject: str, message_prop: str, country_code: str, emails=None): try: user = User.objects.get(id=user_id) user.send_email(subject=_(subject), - message=getattr(user, message_prop, lambda _: '')(country_code)) + message=getattr(user, message_prop, lambda _: '')(country_code), + emails=emails) except: cur_frame = inspect.currentframe() cal_frame = inspect.getouterframes(cur_frame, 2) @@ -35,9 +36,9 @@ def confirm_new_email_address(user_id, country_code): @shared_task -def change_email_address(user_id, country_code): +def change_email_address(user_id, country_code, emails=None): """Send email to user new email.""" - send_email(user_id, 'Validate new email address', 'change_email_template', country_code) + send_email(user_id, 'Validate new email address', 'change_email_template', country_code, emails) @shared_task From 88fa3421dea1ea23fc7978a68843bf1cd0583a48 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 20/41] Fix news email template --- project/templates/news/news_email.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project/templates/news/news_email.html b/project/templates/news/news_email.html index 0227b9de..06fe610e 100644 --- a/project/templates/news/news_email.html +++ b/project/templates/news/news_email.html @@ -35,7 +35,7 @@
{{ description | safe }}
- +
Go to news
@@ -71,7 +71,7 @@
- + From effacc21926546e6ed1787188bbe2281e9b3f3a9 Mon Sep 17 00:00:00 2001 From: Kuroshini Date: Wed, 16 Oct 2019 14:11:07 +0300 Subject: [PATCH 21/41] News email pictures --- project/templates/news/news_email.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/project/templates/news/news_email.html b/project/templates/news/news_email.html index 06fe610e..c2ae227c 100644 --- a/project/templates/news/news_email.html +++ b/project/templates/news/news_email.html @@ -19,7 +19,7 @@
@@ -44,20 +44,20 @@