diff --git a/apps/account/models.py b/apps/account/models.py
index 3eb07722..e06727f2 100644
--- a/apps/account/models.py
+++ b/apps/account/models.py
@@ -1,10 +1,12 @@
"""Account models"""
+from datetime import datetime
+
from django.conf import settings
from django.contrib.auth.models import AbstractUser, UserManager as BaseUserManager
from django.contrib.auth.tokens import default_token_generator as password_token_generator
from django.core.mail import send_mail
from django.db import models
-from django.template.loader import render_to_string
+from django.template.loader import render_to_string, get_template
from django.utils import timezone
from django.utils.encoding import force_bytes
from django.utils.html import mark_safe
@@ -15,6 +17,7 @@ from rest_framework.authtoken.models import Token
from authorization.models import Application
from establishment.models import Establishment
from location.models import Country
+from main.models import SiteSettings
from utils.models import GMTokenGenerator
from utils.models import ImageMixin, ProjectBaseMixin, PlatformMixin
from utils.tokens import GMRefreshToken
@@ -158,19 +161,21 @@ 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),
+ 'message': str(message[0]),
+ 'html_message': message[1],
'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):
@@ -192,12 +197,20 @@ class User(AbstractUser):
"""Get base64 value for user by primary key identifier"""
return urlsafe_base64_encode(force_bytes(self.pk))
- @property
- def base_template(self):
+ def base_template(self, country_code='www', username='', subject=''):
"""Base email template"""
- return {'domain_uri': settings.DOMAIN_URI,
- 'uidb64': self.get_user_uidb64,
- 'site_name': settings.SITE_NAME}
+ socials = SiteSettings.objects.by_country_code(country_code).first()
+ return {
+ 'title': subject,
+ 'domain_uri': settings.DOMAIN_URI,
+ 'uidb64': self.get_user_uidb64,
+ 'site_name': settings.SITE_NAME,
+ 'year': datetime.now().year,
+ 'twitter_page_url': socials.twitter_page_url if socials else '#',
+ 'instagram_page_url': socials.instagram_page_url if socials else '#',
+ 'facebook_page_url': socials.facebook_page_url if socials else '#',
+ 'send_to': username,
+ }
@property
def image_tag(self):
@@ -207,41 +220,41 @@ class User(AbstractUser):
def cropped_image_tag(self):
return mark_safe(f'')
- def reset_password_template(self, country_code):
+ def reset_password_template(self, country_code, username, subject):
"""Get reset password template"""
context = {'token': self.reset_password_token,
'country_code': country_code}
- context.update(self.base_template)
+ context.update(self.base_template(country_code, username, subject))
return render_to_string(
template_name=settings.RESETTING_TOKEN_TEMPLATE,
- context=context)
+ context=context), get_template(settings.RESETTING_TOKEN_TEMPLATE).render(context)
- def notify_password_changed_template(self, country_code):
+ def notify_password_changed_template(self, country_code, username, subject):
"""Get notification email template"""
context = {'contry_code': country_code}
- context.update(self.base_template)
+ context.update(self.base_template(country_code, username, subject))
return render_to_string(
template_name=settings.NOTIFICATION_PASSWORD_TEMPLATE,
context=context,
- )
+ ), get_template(settings.NOTIFICATION_PASSWORD_TEMPLATE).render(context)
- def confirm_email_template(self, country_code):
+ def confirm_email_template(self, country_code, username, subject):
"""Get confirm email template"""
context = {'token': self.confirm_email_token,
'country_code': country_code}
- context.update(self.base_template)
+ context.update(self.base_template(country_code, username, subject))
return render_to_string(
template_name=settings.CONFIRM_EMAIL_TEMPLATE,
- context=context)
+ context=context), get_template(settings.CONFIRM_EMAIL_TEMPLATE).render(context)
- def change_email_template(self, country_code):
+ def change_email_template(self, country_code, username, subject):
"""Get change email template"""
context = {'token': self.change_email_token,
'country_code': country_code}
- context.update(self.base_template)
+ context.update(self.base_template(country_code, username, subject))
return render_to_string(
template_name=settings.CHANGE_EMAIL_TEMPLATE,
- context=context)
+ context=context), get_template(settings.CHANGE_EMAIL_TEMPLATE).render(context)
@property
def favorite_establishment_ids(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..8afe1545 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, user.username, _(subject)),
+ 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
diff --git a/apps/account/transfer_data.py b/apps/account/transfer_data.py
index c39e0ac1..75e0d8ee 100644
--- a/apps/account/transfer_data.py
+++ b/apps/account/transfer_data.py
@@ -1,28 +1,55 @@
-from django.db.models import Value, IntegerField, F
from pprint import pprint
-from transfer.models import Profiles, Accounts
+
+from django.db.models import Q
+
+from transfer.models import Accounts, Identities
from transfer.serializers.account import UserSerializer
+from transfer.serializers.user_social_auth import UserSocialAuthSerializer
+
+STOP_LIST = (
+ 'cyril@tomatic.net',
+ 'cyril2@tomatic.net',
+ 'd.sadykova@id-east.ru',
+ 'd.sadykova@octopod.ru',
+ 'n.yurchenko@id-east.ru',
+)
def transfer_user():
# queryset = Profiles.objects.all()
- # queryset = queryset.annotate(nickname=F("account__nickname"))
- # queryset = queryset.annotate(email=F("account__email"))
- stop_list = ['cyril@tomatic.net',
- 'cyril2@tomatic.net',
- 'd.sadykova@id-east.ru',
- 'd.sadykova@octopod.ru',
- 'n.yurchenko@id-east.ru']
- queryset = Accounts.objects.filter(confirmed_at__isnull=False).exclude(email__in=stop_list)
+ # queryset = queryset.annotate(nickname=F('account__nickname'))
+ # queryset = queryset.annotate(email=F('account__email'))
+
+ queryset = Accounts.objects.filter(confirmed_at__isnull=False).exclude(email__in=STOP_LIST)
serialized_data = UserSerializer(data=list(queryset.values()), many=True)
if serialized_data.is_valid():
serialized_data.save()
else:
- pprint(f"News serializer errors: {serialized_data.errors}")
+ pprint(f'News serializer errors: {serialized_data.errors}')
+
+
+def transfer_identities():
+ queryset = Identities.objects.exclude(
+ Q(account_id__isnull=True) |
+ Q(account__confirmed_at__isnull=True) |
+ Q(account__email__in=STOP_LIST)
+ ).values_list(
+ 'account_id',
+ 'provider',
+ 'uid',
+ )
+
+ serialized_data = UserSocialAuthSerializer(data=list(queryset.values()), many=True)
+
+ if serialized_data.is_valid():
+ serialized_data.save()
+ else:
+ pprint(f'UserSocialAuth serializer errors: {serialized_data.errors}')
data_types = {
- "account": [transfer_user]
+ 'account': [transfer_user],
+ 'identities': [transfer_identities],
}
diff --git a/apps/authorization/models.py b/apps/authorization/models.py
index c295329c..f6476db5 100644
--- a/apps/authorization/models.py
+++ b/apps/authorization/models.py
@@ -33,7 +33,7 @@ class Application(PlatformMixin, AbstractApplication):
swappable = "OAUTH2_PROVIDER_APPLICATION_MODEL"
def natural_key(self):
- return (self.client_id,)
+ return self.client_id
class JWTAccessTokenManager(models.Manager):
diff --git a/apps/authorization/serializers/common.py b/apps/authorization/serializers/common.py
index 13121f78..d99a2dc2 100644
--- a/apps/authorization/serializers/common.py
+++ b/apps/authorization/serializers/common.py
@@ -38,13 +38,13 @@ class SignupSerializer(serializers.ModelSerializer):
valid = utils_methods.username_validator(username=value)
if not valid:
raise utils_exceptions.NotValidUsernameError()
- if account_models.User.objects.filter(username__icontains=value).exists():
+ if account_models.User.objects.filter(username__ilike=value).exists():
raise serializers.ValidationError()
return value
def validate_email(self, value):
"""Validate email"""
- if account_models.User.objects.filter(email__icontains=value).exists():
+ if account_models.User.objects.filter(email__ilike=value).exists():
raise serializers.ValidationError()
return value
diff --git a/apps/authorization/tasks.py b/apps/authorization/tasks.py
index cb186142..d44c2b5c 100644
--- a/apps/authorization/tasks.py
+++ b/apps/authorization/tasks.py
@@ -16,7 +16,7 @@ def send_confirm_email(user_id: int, country_code: str):
try:
obj = account_models.User.objects.get(id=user_id)
obj.send_email(subject=_('Email confirmation'),
- message=obj.confirm_email_template(country_code))
+ message=obj.confirm_email_template(country_code, obj.username, _('Email confirmation')))
except Exception as e:
logger.error(f'METHOD_NAME: {send_confirm_email.__name__}\n'
f'DETAIL: user {user_id}, - {e}')
diff --git a/apps/authorization/views/common.py b/apps/authorization/views/common.py
index a61981c3..9d2069f2 100644
--- a/apps/authorization/views/common.py
+++ b/apps/authorization/views/common.py
@@ -30,24 +30,17 @@ from utils.views import JWTGenericViewMixin
# OAuth2
class BaseOAuth2ViewMixin(generics.GenericAPIView):
"""BaseMixin for classic auth views"""
- def get_client_id(self, source) -> str:
- """Get application client id"""
- qs = Application.objects.by_source(source=source)
- if qs.exists():
- return qs.first().client_id
- else:
- raise utils_exceptions.ServiceError(data={
- 'detail': _('Application is not found')})
- def get_client_secret(self, source) -> str:
- """Get application client id"""
- if source == Application.MOBILE:
- qs = Application.objects.by_source(source=source)
- if qs.exists:
- return qs.first().client_secret
- else:
- raise utils_exceptions.ServiceError(data={
- 'detail': _('Not found an application with this source')})
+ def get_client_credentials(self, source) -> dict:
+ """Get application credentials by source."""
+ credentials = {}
+ qs = Application.objects.filter(authorization_grant_type=Application.GRANT_PASSWORD,
+ source=source)
+ if qs.exists():
+ application = qs.first()
+ credentials = dict(client_id=application.client_id,
+ client_secret=application.client_secret)
+ return credentials
class OAuth2ViewMixin(CsrfExemptMixin, OAuthLibMixin, BaseOAuth2ViewMixin):
@@ -59,20 +52,22 @@ class OAuth2ViewMixin(CsrfExemptMixin, OAuthLibMixin, BaseOAuth2ViewMixin):
def prepare_request_data(self, validated_data: dict) -> dict:
"""Preparing request data"""
source = validated_data.get('source')
- # Set OAuth2 request parameters
- _request_data = {
- 'client_id': self.get_client_id(source)
- }
- # Fill client secret parameter by platform
- if validated_data.get('source') == Application.MOBILE:
- _request_data['client_secret'] = self.get_client_secret(source)
- # Fill token parameter if transfer
- if validated_data.get('token'):
- _request_data['token'] = validated_data.get('token')
- if _request_data:
- return _request_data
+ credentials = self.get_client_credentials(source=source)
+
+ client_id = credentials.get('client_id')
+ client_secret = credentials.get('client_secret')
+ token = validated_data.get('token')
+
+ if client_id and client_secret and token:
+ return {
+ 'client_id': client_id,
+ 'client_secret': client_secret,
+ 'token': token,
+ }
else:
- raise utils_exceptions.ServiceError()
+ raise utils_exceptions.ServiceError(data={
+ 'detail': _('Validation OAuth2 request data error')
+ })
# Sign in via Facebook
diff --git a/apps/comment/admin.py b/apps/comment/admin.py
index 855f6b3e..061c9c8d 100644
--- a/apps/comment/admin.py
+++ b/apps/comment/admin.py
@@ -6,3 +6,4 @@ from . import models
@admin.register(models.Comment)
class CommentModelAdmin(admin.ModelAdmin):
"""Model admin for model Comment"""
+ raw_id_fields = ('user', 'country')
diff --git a/apps/comment/models.py b/apps/comment/models.py
index 29021677..3a8c8c37 100644
--- a/apps/comment/models.py
+++ b/apps/comment/models.py
@@ -32,21 +32,16 @@ class CommentQuerySet(ContentTypeQuerySetMixin):
class Comment(ProjectBaseMixin):
"""Comment model."""
text = models.TextField(verbose_name=_('Comment text'))
- 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'))
+ 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'))
+ country = models.ForeignKey(Country, verbose_name=_('Country'), on_delete=models.SET_NULL, null=True)
+ old_id = models.IntegerField(null=True, blank=True, default=None)
+
content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
objects = CommentQuerySet.as_manager()
- country = models.ForeignKey(Country, verbose_name=_('Country'),
- on_delete=models.SET_NULL, null=True)
- old_id = models.IntegerField(null=True, blank=True, default=None)
-
class Meta:
"""Meta class"""
diff --git a/apps/comment/transfer_data.py b/apps/comment/transfer_data.py
index 3a291b86..843da78f 100644
--- a/apps/comment/transfer_data.py
+++ b/apps/comment/transfer_data.py
@@ -1,11 +1,31 @@
from pprint import pprint
+
+from django.db.models import Q
+
+from account.transfer_data import STOP_LIST
from transfer.models import Comments
from transfer.serializers.comments import CommentSerializer
def transfer_comments():
- queryset = Comments.objects.filter(account__isnull=False, mark__isnull=False)\
- .only("id", "comment", "mark", "locale", "establishment_id", "account_id")
+ # В queryset исключены объекты по условию в связанные моделях
+ # см. transfer_establishment() и transfer_user()
+ queryset = Comments.objects.exclude(
+ Q(establishment__type='Wineyard') |
+ Q(establishment__location__timezone__isnull=True) |
+ Q(account__confirmed_at__isnull=True) |
+ Q(account__email__in=STOP_LIST)
+ ).filter(
+ account__isnull=False,
+ mark__isnull=False
+ ).only(
+ 'id',
+ 'comment',
+ 'mark',
+ 'locale',
+ 'establishment_id',
+ 'account_id',
+ )
serialized_data = CommentSerializer(data=list(queryset.values()), many=True)
if serialized_data.is_valid():
@@ -15,7 +35,7 @@ def transfer_comments():
data_types = {
- "tmp": [
- # transfer_comments
+ 'comment': [
+ transfer_comments
]
}
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..acaeb324
--- /dev/null
+++ b/apps/establishment/management/commands/add_empl_position.py
@@ -0,0 +1,57 @@
+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.
+ Run after add_position and add_employee!'''
+
+ 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 employee position objects.'))
diff --git a/apps/establishment/management/commands/add_employee.py b/apps/establishment/management/commands/add_employee.py
new file mode 100644
index 00000000..4abf588a
--- /dev/null
+++ b/apps/establishment/management/commands/add_employee.py
@@ -0,0 +1,38 @@
+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):
+ 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(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)
+ 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
new file mode 100644
index 00000000..0a456a69
--- /dev/null
+++ b/apps/establishment/management/commands/add_position.py
@@ -0,0 +1,35 @@
+from django.core.management.base import BaseCommand
+from django.db import 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}))
+
+ p = Position.objects.bulk_create(objects)
+ self.stdout.write(self.style.WARNING(f'Created positions objects.'))
diff --git a/apps/establishment/migrations/0055_auto_20191106_0740.py b/apps/establishment/migrations/0055_auto_20191106_0740.py
new file mode 100644
index 00000000..78b1c027
--- /dev/null
+++ b/apps/establishment/migrations/0055_auto_20191106_0740.py
@@ -0,0 +1,28 @@
+# Generated by Django 2.2.4 on 2019-11-06 07:40
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('establishment', '0054_auto_20191103_2117'),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name='establishment',
+ old_name='name_translated',
+ new_name='index_name',
+ ),
+ migrations.AlterField(
+ model_name='establishment',
+ name='index_name',
+ field=models.CharField(default='', max_length=255, verbose_name='Index name'),
+ ),
+ migrations.AddField(
+ model_name='establishment',
+ name='transliterated_name',
+ field=models.CharField(default='', max_length=255, verbose_name='Transliterated name'),
+ ),
+ ]
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/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/migrations/0058_merge_20191106_0921.py b/apps/establishment/migrations/0058_merge_20191106_0921.py
new file mode 100644
index 00000000..61f686b9
--- /dev/null
+++ b/apps/establishment/migrations/0058_merge_20191106_0921.py
@@ -0,0 +1,14 @@
+# Generated by Django 2.2.4 on 2019-11-06 09:21
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('establishment', '0055_auto_20191106_0740'),
+ ('establishment', '0057_establishmentemployee_old_id'),
+ ]
+
+ operations = [
+ ]
diff --git a/apps/establishment/models.py b/apps/establishment/models.py
index 8ea4601b..75d3f6e9 100644
--- a/apps/establishment/models.py
+++ b/apps/establishment/models.py
@@ -301,8 +301,9 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
name = models.CharField(_('name'), max_length=255, default='')
- name_translated = models.CharField(_('Transliterated name'),
- max_length=255, default='')
+ transliterated_name = models.CharField(default='', max_length=255,
+ verbose_name=_('Transliterated name'))
+ index_name = models.CharField(_('Index name'), max_length=255, default='')
description = TJSONField(blank=True, null=True, default=None,
verbose_name=_('description'),
help_text='{"en-GB":"some text"}')
@@ -471,10 +472,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):
@@ -557,11 +558,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()
@@ -578,6 +582,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."""
diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py
index f1fb40a5..8ea41990 100644
--- a/apps/establishment/serializers/back.py
+++ b/apps/establishment/serializers/back.py
@@ -5,6 +5,7 @@ from establishment.serializers import (
EstablishmentBaseSerializer, PlateSerializer, ContactEmailsSerializer,
ContactPhonesSerializer, SocialNetworkRelatedSerializers,
EstablishmentTypeBaseSerializer)
+from location.serializers import AddressDetailSerializer
from main.models import Currency
from utils.decorators import with_base_attributes
from utils.serializers import TimeZoneChoiceField
@@ -28,6 +29,8 @@ class EstablishmentListCreateSerializer(EstablishmentBaseSerializer):
fields = [
'id',
'name',
+ 'transliterated_name',
+ 'index_name',
'website',
'phones',
'emails',
@@ -53,6 +56,7 @@ class EstablishmentRUDSerializer(EstablishmentBaseSerializer):
source='establishment_type',
queryset=models.EstablishmentType.objects.all(), write_only=True
)
+ address = AddressDetailSerializer()
phones = ContactPhonesSerializer(read_only=False, many=True, )
emails = ContactEmailsSerializer(read_only=False, many=True, )
socials = SocialNetworkRelatedSerializers(read_only=False, many=True, )
@@ -73,7 +77,8 @@ class EstablishmentRUDSerializer(EstablishmentBaseSerializer):
'socials',
'image_url',
# TODO: check in admin filters
- 'is_publish'
+ 'is_publish',
+ 'address'
]
diff --git a/apps/establishment/serializers/common.py b/apps/establishment/serializers/common.py
index 50a7acbe..108f8dd0 100644
--- a/apps/establishment/serializers/common.py
+++ b/apps/establishment/serializers/common.py
@@ -196,7 +196,8 @@ class EstablishmentBaseSerializer(ProjectModelSerializer):
fields = [
'id',
'name',
- 'name_translated',
+ 'transliterated_name',
+ 'index_name',
'price_level',
'toque_number',
'public_mark',
diff --git a/apps/establishment/transfer_data.py b/apps/establishment/transfer_data.py
index b178b18a..15f9524d 100644
--- a/apps/establishment/transfer_data.py
+++ b/apps/establishment/transfer_data.py
@@ -1,6 +1,5 @@
from pprint import pprint
-import requests
from django.db.models import Q, F
from establishment.models import Establishment
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):
diff --git a/apps/establishment/views/web.py b/apps/establishment/views/web.py
index 05391827..b01c8c49 100644
--- a/apps/establishment/views/web.py
+++ b/apps/establishment/views/web.py
@@ -162,7 +162,7 @@ class EstablishmentNearestRetrieveView(EstablishmentListView, generics.ListAPIVi
qs = super(EstablishmentNearestRetrieveView, self).get_queryset()
if lat and lon and radius and unit:
- center = Point(float(lat), float(lon))
+ center = Point(float(lon), float(lat))
filter_kwargs = {'center': center, 'radius': float(radius), 'unit': unit}
return qs.by_distance_from_point(**{k: v for k, v in filter_kwargs.items()
if v is not None})
diff --git a/apps/location/serializers/common.py b/apps/location/serializers/common.py
index af0cc4c3..554a306b 100644
--- a/apps/location/serializers/common.py
+++ b/apps/location/serializers/common.py
@@ -69,6 +69,7 @@ class CitySerializer(serializers.ModelSerializer):
queryset=models.Country.objects.all(),
write_only=True
)
+ country = CountrySerializer()
class Meta:
model = models.City
@@ -79,6 +80,7 @@ class CitySerializer(serializers.ModelSerializer):
'region',
'region_id',
'country_id',
+ 'country',
'postal_code',
'is_island',
'city_gallery'
diff --git a/apps/main/management/__init__.py b/apps/main/management/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/main/management/commands/__init__.py b/apps/main/management/commands/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/apps/main/management/commands/add_award.py b/apps/main/management/commands/add_award.py
new file mode 100644
index 00000000..85a613cf
--- /dev/null
+++ b/apps/main/management/commands/add_award.py
@@ -0,0 +1,40 @@
+from django.core.management.base import BaseCommand
+from django.db import connections
+from establishment.management.commands.add_position import namedtuplefetchall
+from main.models import Award, AwardType
+from establishment.models import Employee
+
+
+class Command(BaseCommand):
+ help = '''Add award from old db to new db.
+ Run after command add_award_type!'''
+
+ def award_sql(self):
+ with connections['legacy'].cursor() as cursor:
+ cursor.execute('''
+ select
+ DISTINCT
+ a.id, a.profile_id, a.title,
+ a.`year` as vintage_year, a.state,
+ t.id as award_type
+ from awards as a
+ join award_types t on t.id = a.award_type_id
+ join profiles p on p.id = a.profile_id
+ ''')
+ return namedtuplefetchall(cursor)
+
+ def handle(self, *args, **kwargs):
+ objects =[]
+ for a in self.award_sql():
+ profile = Employee.objects.filter(old_id=a.profile_id).first()
+ type = AwardType.objects.filter(old_id=a.award_type).first()
+ state = Award.PUBLISHED if a.state == 'published' else Award.WAITING
+ if profile and type:
+ award = Award(award_type=type, vintage_year=a.vintage_year,
+ title={"en-GB": a.title}, state=state,
+ content_object=profile, old_id=a.id)
+ objects.append(award)
+ awards = Award.objects.bulk_create(objects)
+ self.stdout.write(self.style.WARNING(f'Created awards objects.'))
+
+
diff --git a/apps/main/management/commands/add_award_type.py b/apps/main/management/commands/add_award_type.py
new file mode 100644
index 00000000..63aa6546
--- /dev/null
+++ b/apps/main/management/commands/add_award_type.py
@@ -0,0 +1,34 @@
+from django.core.management.base import BaseCommand
+from django.db import connections
+from establishment.management.commands.add_position import namedtuplefetchall
+from main.models import AwardType
+from location.models import Country
+
+
+class Command(BaseCommand):
+ help = '''Add award types from old db to new db.
+ Run after migrate country code!'''
+
+ def award_types_sql(self):
+ with connections['legacy'].cursor() as cursor:
+ cursor.execute('''
+ SELECT
+ DISTINCT
+ at.id, TRIM(at.title) AS name,
+ s.country_code_2 AS country_code
+ FROM award_types as at
+ JOIN sites s on s.id = at.site_id
+ WHERE LENGTH(TRIM(at.title))>0
+ ''')
+ return namedtuplefetchall(cursor)
+
+ def handle(self, *args, **kwargs):
+ objects =[]
+ for a in self.award_types_sql():
+ country = Country.objects.filter(code=a.country_code).first()
+ if country:
+ type = AwardType(name=a.name, old_id=a.id)
+ type.country = country
+ objects.append(type)
+ types = AwardType.objects.bulk_create(objects)
+ self.stdout.write(self.style.WARNING(f'Created award types objects.'))
\ No newline at end of file
diff --git a/apps/main/migrations/0032_awardtype_old_id.py b/apps/main/migrations/0032_awardtype_old_id.py
new file mode 100644
index 00000000..7a9e9913
--- /dev/null
+++ b/apps/main/migrations/0032_awardtype_old_id.py
@@ -0,0 +1,18 @@
+# Generated by Django 2.2.4 on 2019-11-06 07:14
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('main', '0031_auto_20191103_2037'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='awardtype',
+ name='old_id',
+ field=models.IntegerField(blank=True, null=True),
+ ),
+ ]
diff --git a/apps/main/migrations/0033_auto_20191106_0744.py b/apps/main/migrations/0033_auto_20191106_0744.py
new file mode 100644
index 00000000..726fa27f
--- /dev/null
+++ b/apps/main/migrations/0033_auto_20191106_0744.py
@@ -0,0 +1,23 @@
+# Generated by Django 2.2.4 on 2019-11-06 07:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('main', '0032_awardtype_old_id'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='award',
+ name='old_id',
+ field=models.IntegerField(blank=True, null=True),
+ ),
+ migrations.AddField(
+ model_name='award',
+ name='state',
+ field=models.PositiveSmallIntegerField(choices=[(0, 'waiting'), (1, 'published')], default=0, verbose_name='State'),
+ ),
+ ]
diff --git a/apps/main/models.py b/apps/main/models.py
index 97fe53c1..9fee60b6 100644
--- a/apps/main/models.py
+++ b/apps/main/models.py
@@ -42,6 +42,9 @@ class SiteSettingsQuerySet(models.QuerySet):
def with_country(self):
return self.filter(country__isnull=False)
+ def by_country_code(self, code):
+ return self.filter(country__code=code)
+
class SiteSettings(ProjectBaseMixin):
subdomain = models.CharField(max_length=255, db_index=True, unique=True,
@@ -161,6 +164,14 @@ class SiteFeature(ProjectBaseMixin):
class Award(TranslatedFieldsMixin, URLImageMixin, models.Model):
"""Award model."""
+ WAITING = 0
+ PUBLISHED = 1
+
+ STATE_CHOICES = (
+ (WAITING,'waiting'),
+ (PUBLISHED, 'published')
+ )
+
award_type = models.ForeignKey('main.AwardType', on_delete=models.CASCADE)
title = TJSONField(
_('title'), null=True, blank=True,
@@ -171,6 +182,11 @@ class Award(TranslatedFieldsMixin, URLImageMixin, models.Model):
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
+ state = models.PositiveSmallIntegerField(default=WAITING, choices=STATE_CHOICES,
+ verbose_name=_('State'))
+
+ old_id = models.IntegerField(null=True, blank=True)
+
def __str__(self):
title = 'None'
lang = TranslationSettings.get_solo().default_language
@@ -184,6 +200,7 @@ class AwardType(models.Model):
country = models.ForeignKey(
'location.Country', verbose_name=_('country'), on_delete=models.CASCADE)
name = models.CharField(_('name'), max_length=255)
+ old_id = models.IntegerField(null=True, blank=True)
def __str__(self):
return self.name
diff --git a/apps/main/views/common.py b/apps/main/views/common.py
index d509f80e..0c2ef6d4 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
diff --git a/apps/news/views.py b/apps/news/views.py
index 990665dd..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'):
- 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
@@ -58,9 +41,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):
diff --git a/apps/search_indexes/documents/establishment.py b/apps/search_indexes/documents/establishment.py
index 7eac2d6c..19d419aa 100644
--- a/apps/search_indexes/documents/establishment.py
+++ b/apps/search_indexes/documents/establishment.py
@@ -90,7 +90,8 @@ class EstablishmentDocument(Document):
fields = (
'id',
'name',
- 'name_translated',
+ 'transliterated_name',
+ 'index_name',
'is_publish',
'price_level',
'toque_number',
diff --git a/apps/search_indexes/serializers.py b/apps/search_indexes/serializers.py
index a356f99b..bbc61735 100644
--- a/apps/search_indexes/serializers.py
+++ b/apps/search_indexes/serializers.py
@@ -96,7 +96,8 @@ class EstablishmentDocumentSerializer(DocumentSerializer):
fields = (
'id',
'name',
- 'name_translated',
+ 'transliterated_name',
+ 'index_name',
'price_level',
'toque_number',
'public_mark',
diff --git a/apps/search_indexes/views.py b/apps/search_indexes/views.py
index 29905125..87b0ba64 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'
+ },
}
@@ -73,8 +79,10 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
search_fields = {
'name': {'fuzziness': 'auto:3,4',
'boost': '2'},
- 'name_translated': {'fuzziness': 'auto:3,4',
- 'boost': '2'},
+ 'transliterated_name': {'fuzziness': 'auto:3,4',
+ 'boost': '2'},
+ 'index_name': {'fuzziness': 'auto:3,4',
+ 'boost': '2'},
'description': {'fuzziness': 'auto'},
}
translated_search_fields = (
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/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."""
diff --git a/apps/transfer/management/commands/transfer.py b/apps/transfer/management/commands/transfer.py
index 06782c9b..d2387d0d 100644
--- a/apps/transfer/management/commands/transfer.py
+++ b/apps/transfer/management/commands/transfer.py
@@ -23,10 +23,12 @@ class Command(BaseCommand):
'menu',
'location_establishment',
'whirligig',
+ 'identities',
]
LONG_DATA_TYPES = [
'update_country_flag',
+ 'comment'
]
def handle(self, *args, **options):
diff --git a/apps/transfer/models.py b/apps/transfer/models.py
index 599445c2..8527eeb6 100644
--- a/apps/transfer/models.py
+++ b/apps/transfer/models.py
@@ -987,3 +987,17 @@ class MetadatumAliases(MigrateMixin):
class Meta:
managed = False
db_table = 'metadatum_aliases'
+
+
+class Identities(MigrateMixin):
+ using = 'legacy'
+
+ account = models.ForeignKey(Accounts, models.DO_NOTHING, blank=True, null=True)
+ provider = models.CharField(max_length=255, blank=True, null=True)
+ uid = models.CharField(max_length=255, blank=True, null=True)
+ created_at = models.DateTimeField()
+ updated_at = models.DateTimeField()
+
+ class Meta:
+ managed = False
+ db_table = 'identities'
diff --git a/apps/transfer/serializers/comments.py b/apps/transfer/serializers/comments.py
index 584370e6..cd4233d1 100644
--- a/apps/transfer/serializers/comments.py
+++ b/apps/transfer/serializers/comments.py
@@ -1,9 +1,10 @@
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):
+class CommentSerializer(serializers.Serializer):
id = serializers.IntegerField()
comment = serializers.CharField()
mark = serializers.DecimalField(max_digits=4, decimal_places=2)
@@ -11,54 +12,45 @@ class CommentSerializer(serializers.ModelSerializer):
account_id = serializers.IntegerField()
establishment_id = serializers.CharField()
- class Meta:
- model = Comment
- fields = (
- "id",
- "comment",
- "mark",
- "locale",
- "account_id",
- "establishment_id"
- )
-
def validate(self, data):
- data = self.set_old_id(data)
- data = self.set_text(data)
- data = self.set_mark(data)
- data = self.set_establishment(data)
- data = self.set_account(data)
+ data.update({
+ 'old_id': data.pop('id'),
+ 'text': data.pop('comment'),
+ 'mark': data['mark'] * -1 if data['mark'] < 0 else data['mark'],
+ 'content_object': self.get_content_object(data),
+ 'user': self.get_account(data),
+ 'country': self.get_country(data),
+ })
+ data.pop('establishment_id')
+ data.pop('account_id')
+ data.pop('locale')
return data
- def set_text(self, data):
- data['text'] = data.pop('comment')
- return data
-
- def set_mark(self, data):
- if data['mark'] < 0:
- data['mark'] = data['mark'] * -1
- return data
-
- def set_account(self, data):
+ def create(self, validated_data):
try:
- data['account'] = User.objects.filter(old_id=data['account_id']).first()
- except User.DoesNotExist as e:
- raise ValueError(f"User account not found with {data}: {e}")
+ return Comment.objects.create(**validated_data)
+ except Exception as e:
+ raise ValueError(f"Error creating comment with {validated_data}: {e}")
- del(data['account_id'])
+ @staticmethod
+ def get_content_object(data):
+ establishment = Establishment.objects.filter(old_id=data['establishment_id']).first()
+ if not establishment:
+ raise ValueError(f"Establishment not found with old_id {data['establishment_id']}: ")
+ return establishment
- return data
+ @staticmethod
+ def get_account(data):
+ user = User.objects.filter(old_id=data['account_id']).first()
+ if not user:
+ raise ValueError(f"User account not found with old_id {data['account_id']}")
+ return user
- def set_establishment(self, data):
- try:
- data['establishment'] = Establishment.objects.filter(old_id=data['account_id']).first()
- except Establishment.DoesNotExist as e:
- raise ValueError(f"Establishment not found with {data}: {e}")
-
- del(data['establishment_id'])
-
- return data
-
- def set_old_id(self, data):
- data['old_id'] = data.pop("id")
- return data
+ @staticmethod
+ def get_country(data):
+ locale = data['locale']
+ country_code = locale[:locale.index("-")] if len(locale) > 2 else locale
+ country = Country.objects.filter(code=country_code).first()
+ if not country:
+ raise ValueError(f"Country not found with code {country_code}")
+ return country
diff --git a/apps/transfer/serializers/user_social_auth.py b/apps/transfer/serializers/user_social_auth.py
new file mode 100644
index 00000000..dc260fa0
--- /dev/null
+++ b/apps/transfer/serializers/user_social_auth.py
@@ -0,0 +1,30 @@
+from rest_framework import serializers
+from social_django.models import UserSocialAuth
+
+from account.models import User
+
+
+class UserSocialAuthSerializer(serializers.Serializer):
+ account_id = serializers.IntegerField()
+ provider = serializers.CharField()
+ uid = serializers.CharField()
+
+ def validate(self, data):
+ data.update({
+ 'user': self.get_account(data),
+ })
+ data.pop('account_id')
+ return data
+
+ def create(self, validated_data):
+ try:
+ return UserSocialAuth.objects.create(**validated_data)
+ except Exception as e:
+ raise ValueError(f"Error creating UserSocialAuth with {validated_data}: {e}")
+
+ @staticmethod
+ def get_account(data):
+ user = User.objects.filter(old_id=data['account_id']).first()
+ if not user:
+ raise ValueError(f"User account not found with old_id {data['account_id']}")
+ return user
diff --git a/project/settings/base.py b/project/settings/base.py
index 686f246e..41233560 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',
]
@@ -490,8 +490,3 @@ PHONENUMBER_DB_FORMAT = 'NATIONAL'
PHONENUMBER_DEFAULT_REGION = "FR"
FALLBACK_LOCALE = 'en-GB'
-
-# TMP TODO remove it later
-# Временный хардкод для демонстрации 4 ноября, потом удалить!
-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..fd832329 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
@@ -54,14 +50,14 @@ DATABASES = {
'HOST': os.environ.get('DB_HOSTNAME'),
'PORT': os.environ.get('DB_PORT'),
},
- # 'legacy': {
- # 'ENGINE': 'django.db.backends.mysql',
- # 'HOST': os.environ.get('MYSQL_HOSTNAME'),
- # 'PORT': os.environ.get('MYSQL_PORT'),
- # 'NAME': os.environ.get('MYSQL_DATABASE'),
- # 'USER': os.environ.get('MYSQL_USER'),
- # 'PASSWORD': os.environ.get('MYSQL_PASSWORD')
- # }
+ 'legacy': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'HOST': os.environ.get('MYSQL_HOSTNAME'),
+ 'PORT': os.environ.get('MYSQL_PORT'),
+ 'NAME': os.environ.get('MYSQL_DATABASE'),
+ 'USER': os.environ.get('MYSQL_USER'),
+ 'PASSWORD': os.environ.get('MYSQL_PASSWORD')
+ }
}
BROKER_URL = 'redis://localhost:6379/1'
diff --git a/project/settings/production.py b/project/settings/production.py
index 4f9e90b7..a531a2ae 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', ]
@@ -37,10 +40,6 @@ sentry_sdk.init(
integrations=[DjangoIntegration()]
)
-# TMP ( TODO remove it later)
-# Временный хардкод для демонстрации 4 ноября, потом удалить!
-HARDCODED_INTERNATIONAL_NEWS_IDS = [8, 9, 10, 11, 15, 17]
-
# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
@@ -55,7 +54,7 @@ DATABASES = {
},
}
-BROKER_URL = 'redis://localhost:6379/1'
+BROKER_URL = 'redis://redis:6379/1'
CELERY_RESULT_BACKEND = BROKER_URL
CELERY_BROKER_URL = BROKER_URL
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
diff --git a/project/templates/account/change_email.html b/project/templates/account/change_email.html
index 6b74d970..efe92766 100644
--- a/project/templates/account/change_email.html
+++ b/project/templates/account/change_email.html
@@ -1,11 +1,80 @@
{% load i18n %}{% autoescape off %}
-{% blocktrans %}You're receiving this email because you want to change email address at {{ site_name }}.{% endblocktrans %}
+
+
+
+
+
+ Follow us
+
+
+
+ Follow us
+
+
+
+ Follow us
+
+
+
+ Follow us
+
Follow us