Merge branch 'develop' into feature/establishment-gallery

# Conflicts:
#	apps/product/serializers/common.py
This commit is contained in:
Anatoly 2019-11-17 14:25:41 +03:00
commit dce951c4f9
24 changed files with 377 additions and 171 deletions

View File

@ -0,0 +1,17 @@
# Generated by Django 2.2.7 on 2019-11-16 11:35
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('advertisement', '0007_auto_20191115_0750'),
]
operations = [
migrations.AlterModelOptions(
name='advertisement',
options={'verbose_name': 'Advertisement', 'verbose_name_plural': 'Advertisements'},
),
]

View File

@ -13,10 +13,50 @@ from utils.methods import get_user_ip
class CheckWhetherBookingAvailable(generics.GenericAPIView):
""" Checks which service to use if establishmend is managed by any """
_VALID_GUESTONLINE_PERIODS = {'lunch', 'dinner', 'afternoon', 'breakfast'}
_GUESTONLINE_PERIODS_TO_PRIOR = {
'breakfast': 1,
'lunch': 2,
'afternoon': 3,
'dinner': 4,
}
permission_classes = (permissions.AllowAny,)
serializer_class = CheckBookingSerializer
pagination_class = None
def _fill_period_template(self, period_template, period_name):
period_template_copy = period_template.copy()
period_template_copy['period'] = period_name
return period_template_copy
def _preprocess_guestonline_response(self, response):
periods = response['periods']
periods_by_name = {period['period']: period for period in periods if 'period' in period}
if not periods_by_name:
raise ValueError('Empty guestonline response')
period_template = iter(periods_by_name.values()).__next__().copy()
period_template.pop('total_left_seats')
period_template['hours'] = []
period_template.pop('period')
processed_periods = [
periods_by_name[period_name]
if period_name in periods_by_name
else self._fill_period_template(period_template, period_name)
for period_name in CheckWhetherBookingAvailable._VALID_GUESTONLINE_PERIODS
]
unnamed_periods = filter(lambda period: 'period' not in period, periods)
for unnamed_period in unnamed_periods:
processed_periods.append(unnamed_period)
response['periods'] = sorted(processed_periods,
key=lambda x: self._GUESTONLINE_PERIODS_TO_PRIOR[x.get('period', 'lunch')])
return response
def get(self, request, *args, **kwargs):
is_booking_available = False
establishment = get_object_or_404(Establishment, pk=kwargs['establishment_id'])
@ -24,12 +64,12 @@ class CheckWhetherBookingAvailable(generics.GenericAPIView):
date = request.query_params.get('date')
g_service = GuestonlineService()
l_service = LastableService()
if (not establishment.lastable_id is None) and l_service \
if establishment.lastable_id is not None and l_service \
.check_whether_booking_available(establishment.lastable_id, date):
is_booking_available = True
service = l_service
service.service_id = establishment.lastable_id
elif (not establishment.guestonline_id is None) and g_service \
elif establishment.guestonline_id is not None and g_service \
.check_whether_booking_available(establishment.guestonline_id,
**g_service.get_certain_keys(request.query_params,
{'date', 'persons'})):
@ -41,7 +81,11 @@ class CheckWhetherBookingAvailable(generics.GenericAPIView):
'available': is_booking_available,
'type': service.service if service else None,
}
response.update({'details': service.response} if service and service.response else {})
service_response = self._preprocess_guestonline_response(service.response) \
if establishment.guestonline_id is not None \
else service.response
response.update({'details': service_response} if service and service.response else {})
return Response(data=response, status=200)
@ -97,8 +141,9 @@ class UpdatePendingBooking(generics.UpdateAPIView):
r = service.update_booking(service.get_certain_keys(data, {
'email', 'phone', 'last_name', 'first_name', 'country_code', 'pending_booking_id', 'note',
}, {
'email', 'phone', 'last_name', 'first_name', 'country_code', 'pending_booking_id',
}))
'email', 'phone', 'last_name', 'first_name',
'country_code', 'pending_booking_id',
}))
if isinstance(r, Response):
return r
if data.get('newsletter'):

View File

@ -1,11 +1,11 @@
from django.shortcuts import get_object_or_404
from rest_framework import generics
from rest_framework import permissions
from collection import models
from utils.pagination import ProjectPageNumberPagination
from django.shortcuts import get_object_or_404
from establishment.serializers import EstablishmentBaseSerializer
from collection.serializers import common as serializers
from establishment.serializers import EstablishmentSimilarSerializer
from utils.pagination import ProjectPageNumberPagination
# Mixins
@ -53,7 +53,7 @@ class CollectionEstablishmentListView(CollectionListView):
"""Retrieve list of establishment for collection."""
lookup_field = 'slug'
pagination_class = ProjectPageNumberPagination
serializer_class = EstablishmentBaseSerializer
serializer_class = EstablishmentSimilarSerializer
def get_queryset(self):
"""

View File

@ -5,7 +5,7 @@ from rest_framework import serializers
from comment import models as comment_models
from comment.serializers import common as comment_serializers
from establishment import models
from location.serializers import AddressBaseSerializer, CitySerializer, AddressDetailSerializer
from location.serializers import AddressBaseSerializer, CitySerializer, AddressDetailSerializer, CityShortSerializer
from main.serializers import AwardSerializer, CurrencySerializer
from tag.serializers import TagBaseSerializer
from timetable.serialziers import ScheduleRUDSerializer
@ -18,6 +18,7 @@ from utils.serializers import ImageBaseSerializer
class ContactPhonesSerializer(serializers.ModelSerializer):
"""Contact phone serializer"""
class Meta:
model = models.ContactPhone
fields = [
@ -27,6 +28,7 @@ class ContactPhonesSerializer(serializers.ModelSerializer):
class ContactEmailsSerializer(serializers.ModelSerializer):
"""Contact email serializer"""
class Meta:
model = models.ContactEmail
fields = [
@ -36,6 +38,7 @@ class ContactEmailsSerializer(serializers.ModelSerializer):
class SocialNetworkRelatedSerializers(serializers.ModelSerializer):
"""Social network serializers."""
class Meta:
model = models.SocialNetwork
fields = [
@ -46,7 +49,6 @@ class SocialNetworkRelatedSerializers(serializers.ModelSerializer):
class PlateSerializer(ProjectModelSerializer):
name_translated = TranslatedField()
currency = CurrencySerializer(read_only=True)
@ -192,6 +194,28 @@ class EstablishmentShortSerializer(serializers.ModelSerializer):
]
class EstablishmentProductShortSerializer(serializers.ModelSerializer):
"""SHORT Serializer for displaying info about an establishment on product page."""
establishment_type = EstablishmentTypeGeoSerializer()
establishment_subtypes = EstablishmentSubTypeBaseSerializer(many=True)
address = AddressBaseSerializer()
city = CityShortSerializer(source='address.city', allow_null=True)
class Meta:
"""Meta class."""
model = models.Establishment
fields = [
'id',
'name',
'index_name',
'slug',
'city',
'establishment_type',
'establishment_subtypes',
'address',
]
class EstablishmentProductSerializer(EstablishmentShortSerializer):
"""Serializer for displaying info about an establishment on product page."""
@ -325,6 +349,12 @@ class EstablishmentDetailSerializer(EstablishmentBaseSerializer):
]
class EstablishmentSimilarSerializer(EstablishmentBaseSerializer):
"""Serializer for Establishment model."""
address = AddressDetailSerializer(read_only=True)
class EstablishmentCommentCreateSerializer(comment_serializers.CommentSerializer):
"""Create comment serializer"""
mark = serializers.IntegerField()

View File

@ -72,7 +72,7 @@ class EstablishmentRecentReviewListView(EstablishmentListView):
class EstablishmentSimilarListView(EstablishmentListView):
"""Resource for getting a list of establishments."""
serializer_class = serializers.EstablishmentBaseSerializer
serializer_class = serializers.EstablishmentSimilarSerializer
pagination_class = EstablishmentPortionPagination
def get_queryset(self):

View File

@ -54,6 +54,20 @@ class RegionSerializer(serializers.ModelSerializer):
'country_id'
]
class CityShortSerializer(serializers.ModelSerializer):
"""Short city serializer"""
country = CountrySerializer(read_only=True)
class Meta:
"""Meta class"""
model = models.City
fields = (
'id',
'name',
'code',
'country',
)
class CitySerializer(serializers.ModelSerializer):
"""City serializer."""

View File

@ -1,8 +1,9 @@
"""Location app views."""
from rest_framework import generics
from rest_framework import permissions
from django.db.models.expressions import RawSQL
from location import models, serializers
from utils.models import get_current_locale
# Mixins
@ -37,7 +38,9 @@ class CountryListView(CountryViewMixin, generics.ListAPIView):
"""List view for model Country."""
pagination_class = None
def get_queryset(self):
qs = super().get_queryset().order_by(RawSQL("name->>%s", (get_current_locale(),)))
return qs
class CountryRetrieveView(CountryViewMixin, generics.RetrieveAPIView):
"""Retrieve view for model Country."""

View File

@ -0,0 +1,20 @@
# Generated by Django 2.2.7 on 2019-11-16 12:48
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('notification', '0002_subscriber_old_id'),
]
operations = [
migrations.AlterField(
model_name='subscriber',
name='user',
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='subscriber', to=settings.AUTH_USER_MODEL, verbose_name='User'),
),
]

View File

@ -74,7 +74,7 @@ class Subscriber(ProjectBaseMixin):
(USABLE, _('Usable')),
)
user = models.OneToOneField(
user = models.ForeignKey(
User,
blank=True,
null=True,

View File

@ -1,7 +1,5 @@
from pprint import pprint
from django.db.models import Count
from transfer.models import EmailAddresses, NewsletterSubscriber
from transfer.serializers.notification import SubscriberSerializer, NewsletterSubscriberSerializer
@ -25,14 +23,14 @@ def transfer_newsletter_subscriber():
'email_address__ip',
'email_address__country_code',
'email_address__locale',
'created_at',
'updated_at',
)
# serialized_data = NewsletterSubscriberSerializer(data=list(queryset.values()), many=True)
# if serialized_data.is_valid():
# serialized_data.save()
# else:
# pprint(f'NewsletterSubscriber serializer errors: {serialized_data.errors}')
serialized_data = NewsletterSubscriberSerializer(data=list(queryset), many=True)
if serialized_data.is_valid():
serialized_data.save()
else:
pprint(f'NewsletterSubscriber serializer errors: {serialized_data.errors}')
data_types = {

View File

@ -83,7 +83,12 @@ class ProductQuerySet(models.QuerySet):
def with_extended_related(self):
"""Returns qs with almost all related objects."""
return self.with_base_related() \
.prefetch_related('tags', 'standards', 'classifications', 'classifications__standard',
.prefetch_related('tags', 'tags__category', 'tags__category__country',
'standards', 'classifications', 'classifications__standard',
'establishment__address', 'establishment__establishment_type',
'establishment__address__city', 'establishment__address__city__country',
'establishment__establishment_subtypes', 'product_gallery',
'gallery', 'product_type', 'subtypes',
'classifications__classification_type', 'classifications__tags') \
.select_related('wine_region', 'wine_sub_region')
@ -247,15 +252,14 @@ class Product(GalleryModelMixin, TranslatedFieldsMixin, BaseAttributes):
@property
def related_tags(self):
return self.tags.exclude(
category__index_name__in=['sugar-content', 'wine-color', 'bottles-produced',
'serial-number', 'grape-variety'])
return self.tags.exclude(category__index_name__in=['sugar-content', 'wine-color', 'bottles-produced',
'serial-number', 'grape-variety']).prefetch_related('category')
@property
def display_name(self):
name = f'{self.name} ' \
f'({self.vintage if self.vintage else "BSA"})'
if self.establishment.name:
if self.establishment and self.establishment.name:
name = f'{self.establishment.name} - ' + name
return name

View File

@ -4,7 +4,7 @@ from rest_framework import serializers
from comment.models import Comment
from comment.serializers import CommentSerializer
from establishment.serializers import EstablishmentShortSerializer, EstablishmentProductSerializer
from establishment.serializers import EstablishmentShortSerializer, EstablishmentProductSerializer, EstablishmentProductShortSerializer
from gallery.models import Image
from product import models
from review.serializers import ReviewShortSerializer
@ -12,13 +12,13 @@ from utils import exceptions as utils_exceptions
from utils.serializers import TranslatedField, FavoritesCreateSerializer, ImageBaseSerializer
from main.serializers import AwardSerializer
from location.serializers import WineRegionBaseSerializer, WineSubRegionBaseSerializer
from tag.serializers import TagBaseSerializer, TagCategoryShortSerializer
from tag.serializers import TagBaseSerializer, TagCategoryProductSerializer
class ProductTagSerializer(TagBaseSerializer):
"""Serializer for model Tag."""
category = TagCategoryShortSerializer(read_only=True)
category = TagCategoryProductSerializer(read_only=True)
class Meta(TagBaseSerializer.Meta):
"""Meta class."""
@ -83,21 +83,12 @@ class ProductStandardBaseSerializer(serializers.ModelSerializer):
)
class ProductCropImageSerializer(serializers.Serializer):
"""Serializer for product image."""
class ProductImageSerializer(ImageBaseSerializer):
"""Serializer for product image."""
auto_crop_images = ProductCropImageSerializer(allow_null=True)
class ProductBaseSerializer(serializers.ModelSerializer):
"""Product base serializer."""
name = serializers.CharField(source='display_name', read_only=True)
product_type = ProductTypeBaseSerializer(read_only=True)
subtypes = ProductSubTypeBaseSerializer(many=True, read_only=True)
establishment_detail = EstablishmentShortSerializer(source='establishment', read_only=True)
establishment_detail = EstablishmentProductShortSerializer(source='establishment', read_only=True)
tags = ProductTagSerializer(source='related_tags', many=True, read_only=True)
wine_region = WineRegionBaseSerializer(read_only=True)
wine_colors = TagBaseSerializer(many=True, read_only=True)
@ -128,6 +119,7 @@ class ProductBaseSerializer(serializers.ModelSerializer):
class ProductDetailSerializer(ProductBaseSerializer):
"""Product detail serializer."""
description_translated = TranslatedField()
establishment_detail = EstablishmentShortSerializer(source='establishment', read_only=True)
review = ReviewShortSerializer(source='last_published_review', read_only=True)
awards = AwardSerializer(many=True, read_only=True)
classifications = ProductClassificationBaseSerializer(many=True, read_only=True)

View File

@ -26,6 +26,10 @@ class ProductListView(ProductBaseView, generics.ListAPIView):
serializer_class = serializers.ProductBaseSerializer
filter_class = filters.ProductFilterSet
def get_queryset(self):
qs = super().get_queryset().with_extended_related()
return qs
class ProductDetailView(ProductBaseView, generics.RetrieveAPIView):
"""Detail view fro model Product."""

View File

@ -95,13 +95,15 @@ class ProductDocument(Document):
},
multi=True
)
name = fields.TextField(attr='display_name', analyzer='english')
name_ru = fields.TextField(attr='display_name', analyzer='russian')
name_fr = fields.TextField(attr='display_name', analyzer='french')
class Django:
model = models.Product
fields = (
'id',
'category',
'name',
'available',
'public_mark',
'slug',

View File

@ -39,7 +39,8 @@ class ProductSubtypeDocumentSerializer(serializers.Serializer):
id = serializers.IntegerField()
name_translated = serializers.SerializerMethodField()
get_name_translated = lambda obj: get_translated_value(obj.name)
def get_name_translated(self, obj):
return get_translated_value(obj.name)
class WineRegionCountryDocumentSerialzer(serializers.Serializer):
@ -64,6 +65,9 @@ class WineRegionDocumentSerializer(serializers.Serializer):
name = serializers.CharField()
country = WineRegionCountryDocumentSerialzer(allow_null=True)
def get_attribute(self, instance):
return instance.wine_region if instance and instance.wine_region else None
class WineColorDocumentSerializer(serializers.Serializer):
"""Wine color ES document serializer,"""
@ -79,6 +83,18 @@ class WineColorDocumentSerializer(serializers.Serializer):
return get_translated_value(obj.label)
class ProductTypeDocumentSerializer(serializers.Serializer):
"""Product type ES document serializer."""
id = serializers.IntegerField()
index_name = serializers.CharField()
name_translated = serializers.SerializerMethodField()
@staticmethod
def get_name_translated(obj):
return get_translated_value(obj.name)
class ProductEstablishmentDocumentSerializer(serializers.Serializer):
"""Related to Product Establishment ES document serializer."""
@ -199,16 +215,12 @@ class ProductDocumentSerializer(DocumentSerializer):
"""Product document serializer"""
tags = TagsDocumentSerializer(many=True)
subtypes = ProductSubtypeDocumentSerializer(many=True)
subtypes = ProductSubtypeDocumentSerializer(many=True, allow_null=True)
wine_region = WineRegionDocumentSerializer(allow_null=True)
wine_colors = WineColorDocumentSerializer(many=True)
product_type = serializers.SerializerMethodField()
product_type = ProductTypeDocumentSerializer(allow_null=True)
establishment_detail = ProductEstablishmentDocumentSerializer(source='establishment', allow_null=True)
@staticmethod
def get_product_type(obj):
return get_translated_value(obj.product_type.name if obj.product_type else {})
class Meta:
"""Meta class."""

View File

@ -91,8 +91,6 @@ class EstablishmentDocumentViewSet(BaseDocumentViewSet):
'boost': 4},
'transliterated_name': {'fuzziness': 'auto:2,5',
'boost': 3},
'index_name': {'fuzziness': 'auto:2,5',
'boost': 2},
'description': {'fuzziness': 'auto:2,5'},
}
translated_search_fields = (
@ -199,7 +197,7 @@ class ProductDocumentViewSet(BaseDocumentViewSet):
"""Product document ViewSet."""
document = ProductDocument
lookup_field = 'slug'
# lookup_field = 'slug'
pagination_class = ProjectMobilePagination
permission_classes = (permissions.AllowAny,)
serializer_class = serializers.ProductDocumentSerializer
@ -212,19 +210,22 @@ class ProductDocumentViewSet(BaseDocumentViewSet):
filter_backends = [
FilteringFilterBackend,
filters.CustomSearchFilterBackend,
GeoSpatialFilteringFilterBackend,
DefaultOrderingFilterBackend,
# GeoSpatialFilteringFilterBackend,
# DefaultOrderingFilterBackend,
]
search_fields = {
'name': {'fuzziness': 'auto:2,5',
'boost': 4},
'boost': 8},
'name_ru': {'fuzziness': 'auto:2,5',
'boost': 6},
'name_fr': {'fuzziness': 'auto:2,5',
'boost': 7},
'transliterated_name': {'fuzziness': 'auto:2,5',
'boost': 3},
'index_name': {'fuzziness': 'auto:2,5',
'boost': 2},
'description': {'fuzziness': 'auto:2,5'},
}
translated_search_fields = (
'description',
)
@ -248,7 +249,7 @@ class ProductDocumentViewSet(BaseDocumentViewSet):
'for_establishment': {
'field': 'establishment.slug',
},
'type': {
'product_type': {
'field': 'product_type.index_name',
},
'subtype': {
@ -259,5 +260,5 @@ class ProductDocumentViewSet(BaseDocumentViewSet):
]
}
}
geo_spatial_filter_fields = {
}
# geo_spatial_filter_fields = {
# }

View File

@ -31,13 +31,18 @@ class TagCategoryFilterSet(TagsBaseFilterSet):
"""TagCategory filterset."""
establishment_type = filters.CharFilter(method='by_establishment_type')
product_type = filters.CharFilter(method='by_product_type')
class Meta:
"""Meta class."""
model = models.TagCategory
fields = ('type',
'establishment_type', )
'establishment_type',
'product_type', )
def by_product_type(self, queryset, name, value):
return queryset.by_product_type(value)
# todo: filter by establishment type
def by_establishment_type(self, queryset, name, value):

View File

@ -3,87 +3,116 @@ from django.core.management.base import BaseCommand
from establishment.models import Establishment, EstablishmentType
from transfer import models as legacy
from tag.models import Tag, TagCategory
from tqdm import tqdm
from django.db import connections
from collections import namedtuple
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()]
def metadata_category_sql():
with connections['legacy'].cursor() as cursor:
cursor.execute(
'''SELECT
`key`,
establishments.type,
key_value_metadata.`value_type`,
public,
key_value_metadata.id as 'old_id'
FROM metadata
LEFT JOIN establishments
ON metadata.establishment_id=establishments.id
LEFT JOIN key_value_metadata
ON metadata.key=key_value_metadata.key_name
GROUP BY
establishments.type,
`key`,
key_value_metadata.`value_type`,
public, old_id;'''
)
return namedtuplefetchall(cursor)
def metadata_tags_sql():
with connections['legacy'].cursor() as cursor:
cursor.execute(
"""
SELECT
value,
`key` as category,
establishment_id
FROM metadata
WHERE establishment_id is not null"""
)
return namedtuplefetchall(cursor)
class Command(BaseCommand):
help = 'Add tags values from old db to new db'
def get_type(self, meta):
meta_type = meta.value_type
if not meta.value_type:
if meta.key == 'wineyard_visits':
meta_type = 'list'
elif meta.key in ['private_room', 'outside_sits']:
meta_type = 'bool'
return meta_type
def get_label(self, text):
sp = text.split('_')
label = ' '.join([sp[0].capitalize()] + sp[1:])
return label
def handle(self, *args, **kwargs):
existing_establishment = Establishment.objects.filter(
old_id__isnull=False, tags__isnull=True
old_id__isnull=False
)
ESTABLISHMENT = 1
SHOP = 2
RESTAURANT = 3
WINEYARD = 4
MAPPER = {
RESTAURANT: EstablishmentType.RESTAURANT,
WINEYARD: EstablishmentType.PRODUCER,
SHOP: EstablishmentType.ARTISAN
'Restaurant': EstablishmentType.RESTAURANT,
'Wineyard': EstablishmentType.PRODUCER,
'Shop': EstablishmentType.ARTISAN
}
# remove old black category
for establishment_tag in tqdm(EstablishmentType.objects.all()):
establishment_tag.tag_categories.remove(*list(
establishment_tag.tag_categories.exclude(
tags__establishments__isnull=False).distinct()))
mapper_values_meta = legacy.KeyValueMetadatumKeyValueMetadatumEstablishments.objects.all()
for key, value in MAPPER.items():
values_meta_id_list = mapper_values_meta.filter(
key_value_metadatum_establishment_id=key
).values_list('key_value_metadatum_id')
# created Tag Category
for meta in tqdm(metadata_category_sql()):
category, _ = TagCategory.objects.update_or_create(
index_name=meta.key,
defaults={
"public": True if meta.public == 1 else False,
"value_type": self.get_type(meta),
"label": {"en-GB": self.get_label(meta.key)}
}
)
est_type, _ = EstablishmentType.objects.get_or_create(index_name=value)
# add to EstablishmentType
est_type = EstablishmentType.objects.get(index_name=MAPPER[meta.type])
if category not in est_type.tag_categories.all():
est_type.tag_categories.add(category)
key_value_metadata = legacy.KeyValueMetadata.objects.filter(
id__in=values_meta_id_list)
count = 0
for meta_tag in tqdm(metadata_tags_sql()):
# create TagCategory
for key_value in key_value_metadata:
tag_category, created = TagCategory.objects.get_or_create(
index_name=key_value.key_name,
)
if created:
tag_category.label = {
'en-GB': key_value.key_name,
'fr-FR': key_value.key_name,
'ru-RU': key_value.key_name,
}
tag_category.value_type = key_value.value_type
tag_category.save()
est_type.tag_categories.add(
tag_category
)
# create Tag
for tag in key_value.metadata_set.filter(
establishment__id__in=list(
existing_establishment.values_list('old_id', flat=True)
)):
new_tag, created = Tag.objects.get_or_create(
value=tag.value,
category=tag_category,
)
if created:
sp = tag.value.split('_')
value = ' '.join([sp[0].capitalize()] + sp[1:])
trans = {
'en-GB': value,
'fr-FR': value,
'ru-RU': value,
}
aliases = legacy.MetadatumAliases.objects.filter(value=tag.value)
for alias in aliases:
trans[alias.locale] = alias.meta_alias
new_tag.label = trans
new_tag.save()
est = existing_establishment.filter(
old_id=tag.establishment_id).first()
if est:
est.tags.add(new_tag)
est.save()
tag, _ = Tag.objects.update_or_create(
category=TagCategory.objects.get(index_name=meta_tag.category),
value=meta_tag.value,
defaults={
"label": {"en-GB": self.get_label(meta_tag.value)}
}
)
establishment = existing_establishment.filter(old_id=meta_tag.establishment_id).first()
if establishment:
if tag not in establishment.tags.all():
establishment.tags.add(tag)
count += 1
self.stdout.write(self.style.WARNING(f'Created {count} tags to Establishment'))

View File

@ -1,19 +1,18 @@
from django.core.management.base import BaseCommand
from establishment.models import Establishment, EstablishmentType
from tag.models import Tag
from transfer import models as legacy
from tag.models import Tag, TagCategory
from tqdm import tqdm
class Command(BaseCommand):
help = 'Add tags translation from old db to new db'
def handle(self, *args, **kwargs):
translation = legacy.MetadatumAliases.objects.all()
# Humanisation for default values
@staticmethod
def humanisation_tag(self):
"""Humanisation for default values."""
tags = Tag.objects.all()
for tag in tags:
for tag in tqdm(tags):
value = tag.label
for k, v in value.items():
if isinstance(v, str) and '_' in v:
@ -22,10 +21,14 @@ class Command(BaseCommand):
tag.label[k] = v
tag.save()
for trans in translation:
def handle(self, *args, **kwargs):
"""Translation for existed tags."""
translation = legacy.MetadatumAliases.objects.all()
# self.humanisation_tag()
for trans in tqdm(translation):
tag = Tag.objects.filter(value=trans.value).first()
if tag:
tag.label.update(
{trans.locale: trans.meta_alias}
)
tag.save()
tag.save()

View File

@ -37,6 +37,7 @@ class Tag(TranslatedFieldsMixin, models.Model):
chosen_tag_settings = models.ManyToManyField(Country, through='ChosenTagSettings')
priority = models.PositiveIntegerField(null=True, default=0)
# It does not make sense since in the old base another structure with duplicates
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
old_id_meta_product = models.PositiveIntegerField(_('old id metadata product'),
@ -100,6 +101,10 @@ class TagCategoryQuerySet(models.QuerySet):
"""Filter by establishment type index name."""
return self.filter(establishment_types__index_name=index_name)
def by_product_type(self, index_name):
"""Filter by product type index name."""
return self.filter(product_types__index_name=index_name)
def with_tags(self, switcher=True):
"""Filter by existing tags."""
return self.exclude(tags__isnull=switcher)

View File

@ -37,6 +37,21 @@ class TagBackOfficeSerializer(TagBaseSerializer):
'category'
)
class TagCategoryProductSerializer(serializers.ModelSerializer):
"""SHORT Serializer for TagCategory"""
label_translated = TranslatedField()
class Meta:
"""Meta class."""
model = models.TagCategory
fields = (
'id',
'label_translated',
'index_name',
)
class TagCategoryBaseSerializer(serializers.ModelSerializer):
"""Serializer for model TagCategory."""

View File

@ -14,8 +14,6 @@ class AdvertisementSerializer(serializers.ModelSerializer):
href = serializers.CharField()
site_id = serializers.PrimaryKeyRelatedField(
queryset=Sites.objects.all())
start_at = serializers.DateTimeField(allow_null=True)
expire_at = serializers.DateTimeField(allow_null=True)
class Meta:
"""Meta class."""
@ -24,29 +22,27 @@ class AdvertisementSerializer(serializers.ModelSerializer):
'id',
'href',
'site_id',
'start_at',
'expire_at',
]
def validate(self, data):
data.update({
'old_id': data.pop('id'),
'url': data.pop('href'),
'site': self.get_site(data.pop('site_id')),
'start': data.pop('start_at', None),
'end': data.pop('expire_at', None),
'site_settings': self.get_site_settings(data.pop('site_id')),
})
return data
def create(self, validated_data):
site = validated_data.pop('site')
obj, _ = self.Meta.model.objects.get_or_create(validated_data)
site = validated_data.pop('site_settings')
url = validated_data.get('url')
obj, _ = self.Meta.model.objects.get_or_create(url=url, defaults=validated_data)
if site and site not in obj.sites.all():
obj.sites.add(site)
return obj
def get_site(self, subdomain):
def get_site_settings(self, subdomain):
subdomain = subdomain.country_code_2 if isinstance(subdomain, Sites) else subdomain
qs = SiteSettings.objects.filter(subdomain=subdomain)
if qs.exists():
@ -89,5 +85,5 @@ class AdvertisementImageSerializer(AdvertisementSerializer):
image_url = validated_data.get('image_url')
if advertisement and image_url:
Page.objects.get_or_create(advertisement=advertisement, image_url=image_url, source=Page.MOBILE)
Page.objects.get_or_create(advertisement=advertisement, image_url=image_url, source=Page.WEB)
self.Meta.model.objects.get_or_create(source=Page.MOBILE, **validated_data)
self.Meta.model.objects.get_or_create(source=Page.WEB, **validated_data)

View File

@ -1,3 +1,4 @@
from django.db import IntegrityError
from rest_framework import serializers
from account.models import User
@ -41,10 +42,10 @@ class NewsletterSubscriberSerializer(serializers.Serializer):
id = serializers.IntegerField()
email_address__email = serializers.CharField()
email_address__account_id = serializers.IntegerField(allow_null=True)
email_address__ip = serializers.CharField(allow_null=True)
email_address__country_code = serializers.CharField(allow_null=True)
email_address__locale = serializers.CharField(allow_null=True)
created_at = serializers.DateTimeField(format='%m-%d-%Y %H:%M:%S')
email_address__ip = serializers.CharField(allow_null=True, allow_blank=True)
email_address__country_code = serializers.CharField(allow_null=True, allow_blank=True)
email_address__locale = serializers.CharField(allow_null=True, allow_blank=True)
updated_at = serializers.DateTimeField(format='%m-%d-%Y %H:%M:%S')
def validate(self, data):
data.update({
@ -53,18 +54,28 @@ class NewsletterSubscriberSerializer(serializers.Serializer):
'ip_address': data.pop('email_address__ip'),
'country_code': data.pop('email_address__country_code'),
'locale': data.pop('email_address__locale'),
'created': data.pop('created_at'),
'created': data.pop('updated_at'),
'user_id': self.get_user(data),
})
data.pop('email_address__account_id')
return data
# def create(self, validated_data):
# obj, _ = Review.objects.update_or_create(
# old_id=validated_data['old_id'],
# defaults=validated_data,
# )
# return obj
def create(self, validated_data):
try:
obj = Subscriber.objects.get(email=validated_data['email'])
except Subscriber.DoesNotExist:
obj = Subscriber.objects.create(**validated_data)
else:
current_data = obj.created
if validated_data['created'] > current_data:
obj.ip_address = validated_data['ip_address']
obj.locale = validated_data['locale']
obj.country_code = validated_data['country_code']
obj.old_id = validated_data['old_id']
obj.created = validated_data['created']
obj.user_id = validated_data['user_id']
obj.save()
return obj
@staticmethod
def get_user(data):
@ -73,6 +84,6 @@ class NewsletterSubscriberSerializer(serializers.Serializer):
return None
user = User.objects.filter(old_id=data['email_address__account_id']).first()
if not user:
raise ValueError(f"User account not found with old_id {data['email_address__account_id']}")
return user.id
if user:
return user.id
return None

View File

@ -80,11 +80,11 @@ LOGGING = {
'py.warnings': {
'handlers': ['console'],
},
'django.db.backends': {
'handlers': ['console', ],
'level': 'DEBUG',
'propagate': False,
},
# 'django.db.backends': {
# 'handlers': ['console', ],
# 'level': 'DEBUG',
# 'propagate': False,
# },
}
}