intermediate commit
This commit is contained in:
parent
e2d71fca8f
commit
2827374911
|
|
@ -343,13 +343,15 @@ class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin):
|
|||
|
||||
def update_count_related_objects(self, nodes: set = ('EstablishmentNode', 'WineNode')):
|
||||
"""Update count of related guide element objects."""
|
||||
descendants = GuideElement.objects.get_root_node(self) \
|
||||
.get_descendants()
|
||||
if descendants:
|
||||
updated_count = descendants.filter(
|
||||
guide_element_type__name__in=nodes).count()
|
||||
self.count_related_objects = updated_count
|
||||
self.save()
|
||||
root_node = GuideElement.objects.get_root_node(self)
|
||||
if root_node:
|
||||
descendants = root_node.get_descendants()
|
||||
|
||||
if descendants:
|
||||
updated_count = descendants.filter(
|
||||
guide_element_type__name__in=nodes).count()
|
||||
self.count_related_objects = updated_count
|
||||
self.save()
|
||||
|
||||
def generate_elements(self):
|
||||
if self.guidefilter:
|
||||
|
|
@ -390,6 +392,12 @@ class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin):
|
|||
self.state = state
|
||||
self.save()
|
||||
|
||||
def export_to_file(self, user_id: int, file_type: str):
|
||||
if settings.USE_CELERY:
|
||||
tasks.export_guide.delay(guide_id=self.id, user_id=user_id, file_type=file_type)
|
||||
else:
|
||||
tasks.export_guide(guide_id=self.id, user_id=user_id, file_type=file_type)
|
||||
|
||||
|
||||
class AdvertorialQuerySet(models.QuerySet):
|
||||
"""QuerySet for model Advertorial."""
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ class AdvertorialBaseSerializer(serializers.ModelSerializer):
|
|||
|
||||
class GuideElementExportSerializer(GuideElementBaseSerializer):
|
||||
"""GuideElement export serializer."""
|
||||
# establishment = EstablishmentGuideElementSerializer(read_only=True,)
|
||||
# ESTABLISHMENT
|
||||
name = serializers.CharField(source='establishment.name', default=None)
|
||||
public_mark = serializers.CharField(source='establishment.public_mark_display', default=None)
|
||||
toque_number = serializers.IntegerField(source='establishment.toque_number', default=None)
|
||||
|
|
@ -239,6 +239,18 @@ class GuideElementExportSerializer(GuideElementBaseSerializer):
|
|||
default=None)
|
||||
advertorial_page = serializers.IntegerField(default=None)
|
||||
|
||||
# PRODUCT
|
||||
product_name = serializers.CharField(source='product.name',
|
||||
default=None)
|
||||
product_review = serializers.DictField(source='product.establishment.last_published_review_data',
|
||||
default=None)
|
||||
product_type = serializers.CharField(source='product.product_type_label',
|
||||
default=None)
|
||||
product_subtypes = serializers.CharField(source='product.product_subtype_labels',
|
||||
default=None)
|
||||
product_address = serializers.CharField(source='product.establishment.address.full_address',
|
||||
default=None)
|
||||
|
||||
class Meta:
|
||||
model = models.GuideElement
|
||||
fields = [
|
||||
|
|
@ -254,7 +266,7 @@ class GuideElementExportSerializer(GuideElementBaseSerializer):
|
|||
# 'section_name',
|
||||
# 'wine_color_section_name',
|
||||
# 'children',
|
||||
# 'label_photo',
|
||||
'label_photo_url',
|
||||
'name',
|
||||
'public_mark',
|
||||
'toque_number',
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ def generate_product_guide_elements(guide_id: int, filter_set: dict):
|
|||
|
||||
guide = Guide.objects.get(id=guide_id)
|
||||
guide.change_state(Guide.BUILDING)
|
||||
queryset_values = Product.objects.filter(**filter_set).values()[0]
|
||||
queryset_values = Product.objects.filter(**filter_set).values()
|
||||
try:
|
||||
for instance in queryset_values:
|
||||
wine_id = instance.get('id')
|
||||
|
|
@ -133,7 +133,6 @@ def generate_product_guide_elements(guide_id: int, filter_set: dict):
|
|||
guide.change_state(Guide.WAITING)
|
||||
logger.error(f'METHOD_NAME: {generate_product_guide_elements.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - {e}')
|
||||
else:
|
||||
guide.update_count_related_objects()
|
||||
guide.change_state(Guide.BUILT)
|
||||
|
||||
|
|
|
|||
|
|
@ -205,7 +205,6 @@ class GuideElementExportDOCView(generics.ListAPIView):
|
|||
"""Overridden get_queryset method."""
|
||||
guide = get_object_or_404(
|
||||
models.Guide.objects.all(), pk=self.kwargs.get('pk'))
|
||||
# todo: put in GuideElement model
|
||||
tasks.export_guide(guide_id=guide.id, user_id=request.user.id, file_type='doc')
|
||||
guide.export_to_file(user_id=request.user.id, file_type='doc')
|
||||
return Response({"success": _('The file will be sent to your email.')},
|
||||
status=status.HTTP_200_OK)
|
||||
|
|
|
|||
|
|
@ -247,13 +247,13 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
'establishment_type': establishment.establishment_type,
|
||||
'address__city__country': establishment.address.city.country
|
||||
}
|
||||
qs = self.exclude(id=establishment.id).filter(**filters)
|
||||
if establishment.establishment_subtypes.exists():
|
||||
filters.update(
|
||||
{'establishment_subtypes__in': establishment.establishment_subtypes.all()})
|
||||
|
||||
return self.exclude(id=establishment.id) \
|
||||
.filter(**filters) \
|
||||
.annotate_distance(point=establishment.location)
|
||||
if establishment.address and establishment.address.coordinates:
|
||||
qs = qs.annotate_distance(point=establishment.location)
|
||||
return qs
|
||||
|
||||
def similar_base_subquery(self, establishment, filters: dict) -> Subquery:
|
||||
"""
|
||||
|
|
@ -262,12 +262,16 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
1 Filter by transmitted filters.
|
||||
2 With ordering by distance.
|
||||
"""
|
||||
qs = self.similar_base(establishment) \
|
||||
.filter(**filters)
|
||||
if establishment.address and establishment.address.coordinates:
|
||||
return Subquery(
|
||||
qs.order_by('distance')
|
||||
.distinct()
|
||||
.values_list('id', flat=True)[:settings.LIMITING_QUERY_OBJECTS]
|
||||
)
|
||||
return Subquery(
|
||||
self.similar_base(establishment)
|
||||
.filter(**filters)
|
||||
.order_by('distance')
|
||||
.distinct()
|
||||
.values_list('id', flat=True)[:settings.LIMITING_QUERY_OBJECTS]
|
||||
qs.values_list('id', flat=True)[:settings.LIMITING_QUERY_OBJECTS]
|
||||
)
|
||||
|
||||
def similar_restaurants(self, restaurant):
|
||||
|
|
@ -284,7 +288,6 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
'establishment_gallery__is_main': True,
|
||||
}
|
||||
)
|
||||
# todo: fix this - replace ids_by_subquery.queryset on ids_by_subquery
|
||||
return self.filter(id__in=ids_by_subquery.queryset) \
|
||||
.annotate_intermediate_public_mark() \
|
||||
.annotate_mark_similarity(mark=restaurant.public_mark) \
|
||||
|
|
@ -307,12 +310,20 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
Return QuerySet with objects that similar to Artisan/Producer(s).
|
||||
:param establishment: Establishment instance
|
||||
"""
|
||||
similarity_rules = {
|
||||
'ordering': [F('same_subtype').desc(), ],
|
||||
'distinctions': ['same_subtype', ]
|
||||
}
|
||||
if establishment.address and establishment.address.coordinates:
|
||||
similarity_rules['ordering'].append(F('distance').asc())
|
||||
similarity_rules['distinctions'].append('distance')
|
||||
|
||||
return self.similar_base(establishment) \
|
||||
.same_subtype(establishment) \
|
||||
.has_published_reviews() \
|
||||
.order_by(F('same_subtype').desc(),
|
||||
F('distance').asc()) \
|
||||
.distinct('same_subtype', 'distance', 'id')
|
||||
.order_by(similarity_rules['ordering']) \
|
||||
.distinct(similarity_rules['distinctions'],
|
||||
'id')
|
||||
|
||||
def by_wine_region(self, wine_region):
|
||||
"""
|
||||
|
|
@ -333,14 +344,20 @@ class EstablishmentQuerySet(models.QuerySet):
|
|||
Return QuerySet with objects that similar to Winery.
|
||||
:param winery: Establishment instance
|
||||
"""
|
||||
similarity_rules = {
|
||||
'ordering': [F('wine_origins__wine_region').asc(),
|
||||
F('wine_origins__wine_sub_region').asc()],
|
||||
'distinctions': ['wine_origins__wine_region',
|
||||
'wine_origins__wine_sub_region']
|
||||
}
|
||||
if winery.address and winery.address.coordinates:
|
||||
similarity_rules['ordering'].append(F('distance').asc())
|
||||
similarity_rules['distinctions'].append('distance')
|
||||
|
||||
return self.similar_base(winery) \
|
||||
.order_by(F('wine_origins__wine_region').asc(),
|
||||
F('wine_origins__wine_sub_region').asc(),
|
||||
F('distance').asc()) \
|
||||
.distinct('wine_origins__wine_region',
|
||||
'wine_origins__wine_sub_region',
|
||||
'distance',
|
||||
'id')
|
||||
.order_by(*similarity_rules['ordering']) \
|
||||
.distinct(*similarity_rules['distinctions'],
|
||||
'id')
|
||||
|
||||
def last_reviewed(self, point: Point):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ from utils.models import (BaseAttributes, ProjectBaseMixin, HasTagsMixin,
|
|||
TranslatedFieldsMixin, TJSONField, FavoritesMixin,
|
||||
GalleryMixin, IntermediateGalleryModelMixin,
|
||||
TypeDefaultImageMixin)
|
||||
from utils.methods import transform_into_readable_str
|
||||
|
||||
|
||||
class ProductType(TypeDefaultImageMixin, TranslatedFieldsMixin, ProjectBaseMixin):
|
||||
|
|
@ -188,28 +189,32 @@ class ProductQuerySet(models.QuerySet):
|
|||
'reviews__status': Review.READY,
|
||||
'product_type': product.product_type,
|
||||
}
|
||||
qs = self.exclude(id=product.id) \
|
||||
.filter(**filters)
|
||||
if product.subtypes.exists():
|
||||
filters.update(
|
||||
{'subtypes__in': product.subtypes.all()})
|
||||
return self.exclude(id=product.id) \
|
||||
.filter(**filters) \
|
||||
.annotate_distance(point=product.establishment.location)
|
||||
if product.establishment.address and product.establishment.location:
|
||||
qs = qs.annotate_distance(point=product.establishment.location)
|
||||
return qs
|
||||
|
||||
def similar(self, slug):
|
||||
def similar(self, product):
|
||||
"""
|
||||
Return QuerySet with objects that similar to Product.
|
||||
:param slug: str product slug
|
||||
:param product: instance of Product model.
|
||||
"""
|
||||
product_qs = self.filter(slug=slug)
|
||||
if product_qs.exists():
|
||||
product = product_qs.first()
|
||||
return self.similar_base(product) \
|
||||
.same_subtype(product) \
|
||||
.order_by(F('same_subtype').desc(),
|
||||
F('distance').asc()) \
|
||||
.distinct('same_subtype', 'distance', 'id')
|
||||
else:
|
||||
return self.none()
|
||||
similarity_rules = {
|
||||
'ordering': [F('same_subtype').desc(), ],
|
||||
'distinction': ['same_subtype', ]
|
||||
}
|
||||
if product.establishment.address and product.establishment.location:
|
||||
similarity_rules['ordering'].append(F('distance').asc())
|
||||
similarity_rules['distinction'].append('distance')
|
||||
return self.similar_base(product) \
|
||||
.same_subtype(product) \
|
||||
.order_by(*similarity_rules['ordering']) \
|
||||
.distinct(*similarity_rules['distinction'],
|
||||
'id')
|
||||
|
||||
|
||||
class Product(GalleryMixin, TranslatedFieldsMixin, BaseAttributes,
|
||||
|
|
@ -389,6 +394,22 @@ class Product(GalleryMixin, TranslatedFieldsMixin, BaseAttributes,
|
|||
if self.wine_origins.exists():
|
||||
return self.wine_origins.first().wine_region
|
||||
|
||||
@property
|
||||
def last_published_review_data(self):
|
||||
if self.last_published_review:
|
||||
return self.last_published_review.text
|
||||
|
||||
@property
|
||||
def establishment_subtype_labels(self):
|
||||
if self.subtypes:
|
||||
return [transform_into_readable_str(label)
|
||||
for label in self.subtypes.all().values_list('index_name', flat=True)]
|
||||
|
||||
@property
|
||||
def wine_region_label(self):
|
||||
if self.wine_region:
|
||||
return self.wine_region.name
|
||||
|
||||
|
||||
class OnlineProductManager(ProductManager):
|
||||
"""Extended manger for OnlineProduct model."""
|
||||
|
|
|
|||
|
|
@ -110,6 +110,6 @@ class SimilarListView(ProductSimilarView):
|
|||
base_product = self.get_base_object()
|
||||
|
||||
if base_product:
|
||||
return qs.has_location().similar(slug=self.kwargs.get('slug'))[:settings.QUERY_OUTPUT_OBJECTS]
|
||||
return qs.has_location().similar(base_product)[:settings.QUERY_OUTPUT_OBJECTS]
|
||||
else:
|
||||
return qs.none()
|
||||
|
|
|
|||
|
|
@ -388,12 +388,6 @@ class SendGuideExport(SendExportBase):
|
|||
document.document.save(self.file_path)
|
||||
self.success = True
|
||||
|
||||
def get_headers(self):
|
||||
headers = list(self.data[0].keys())
|
||||
headers.pop(headers.index('node_name'))
|
||||
self.success = True
|
||||
return headers
|
||||
|
||||
def get_data(self):
|
||||
return self.data
|
||||
|
||||
|
|
@ -432,6 +426,34 @@ class SendGuideExport(SendExportBase):
|
|||
print(f'ok: {self.file_path}')
|
||||
self.send_email()
|
||||
|
||||
def get_headers(self):
|
||||
"""Get headers for model Establishment."""
|
||||
exclude_headers = ['node_name', ]
|
||||
headers = list(self.data[0].keys())
|
||||
|
||||
if self.guide.RESTAURANT or self.guide.ARTISAN:
|
||||
exclude_headers.append('product_name', )
|
||||
if self.guide.WINE:
|
||||
exclude_headers.extend([
|
||||
'name',
|
||||
'public_mark',
|
||||
'toque_number',
|
||||
'schedule',
|
||||
'address',
|
||||
'phones',
|
||||
'establishment_type',
|
||||
'establishment_subtypes',
|
||||
'review',
|
||||
'price_level',
|
||||
'metadata',
|
||||
])
|
||||
|
||||
for name in set(exclude_headers):
|
||||
headers.pop(headers.index(name))
|
||||
else:
|
||||
self.success = True
|
||||
return headers
|
||||
|
||||
def make_csv_file(self):
|
||||
file_header = self.get_headers()
|
||||
if not self.success:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user