added endpoint to add/remove establishment from guide
This commit is contained in:
parent
202b8c8d96
commit
8df96716cc
|
|
@ -1,21 +1,21 @@
|
|||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.fields import ContentType
|
||||
from django.contrib.postgres.fields import JSONField
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from mptt.models import MPTTModel, TreeForeignKey
|
||||
from slugify import slugify
|
||||
|
||||
from collection import tasks
|
||||
from establishment.models import Establishment
|
||||
from location.models import Country, Region, WineRegion, WineSubRegion, City
|
||||
from product.models import Product
|
||||
from review.models import Review
|
||||
from collection import tasks
|
||||
from translation.models import Language
|
||||
from utils.methods import transform_into_readable_str
|
||||
from utils.methods import transform_into_section_name
|
||||
from utils.models import (
|
||||
ProjectBaseMixin, TJSONField, TranslatedFieldsMixin,
|
||||
URLImageMixin, IntermediateGalleryModelMixin
|
||||
|
|
@ -177,9 +177,13 @@ class GuideQuerySet(models.QuerySet):
|
|||
return self.with_base_related().prefetch_related('guideelement_set')
|
||||
|
||||
def by_country_id(self, country_id):
|
||||
"""Return QuerySet filtered by country code."""
|
||||
"""Return QuerySet filtered by country id."""
|
||||
return self.filter(country_json__id__contains=country_id)
|
||||
|
||||
def by_country_code(self, country_code):
|
||||
"""Return QuerySet filtered by country code."""
|
||||
return self.filter(site__country__code=country_code)
|
||||
|
||||
def annotate_in_restaurant_section(self):
|
||||
"""Annotate flag if GuideElement in RestaurantSectionNode."""
|
||||
restaurant_guides = models.Subquery(
|
||||
|
|
@ -420,6 +424,32 @@ class Guide(ProjectBaseMixin, CollectionNameMixin, CollectionDateMixin):
|
|||
filter_set=self.guidefilter.product_filter_set,
|
||||
)
|
||||
|
||||
def extend_establishment_guide(self, establishment_id: int):
|
||||
if self.guide_type in [self.ARTISAN, self.RESTAURANT]:
|
||||
if settings.USE_CELERY:
|
||||
tasks.populate_establishment_guide.delay(
|
||||
guide_id=self.id,
|
||||
establishment_id=establishment_id,
|
||||
)
|
||||
else:
|
||||
tasks.populate_establishment_guide(
|
||||
guide_id=self.id,
|
||||
establishment_id=establishment_id,
|
||||
)
|
||||
|
||||
def remove_establishment(self, establishment_id: int):
|
||||
if self.guide_type in [self.ARTISAN, self.RESTAURANT]:
|
||||
if settings.USE_CELERY:
|
||||
tasks.remove_establishment_guide.delay(
|
||||
guide_id=self.id,
|
||||
establishment_id=establishment_id,
|
||||
)
|
||||
else:
|
||||
tasks.remove_establishment_guide(
|
||||
guide_id=self.id,
|
||||
establishment_id=establishment_id,
|
||||
)
|
||||
|
||||
def regenerate_elements(self):
|
||||
# get Root node
|
||||
root_node = GuideElement.objects.get_root_node(self)
|
||||
|
|
@ -905,7 +935,7 @@ class GuideElementManager(models.Manager):
|
|||
parent_node_qs = GuideElement.objects.filter(id=yard_node_id)
|
||||
|
||||
if not wine_color_name.endswith('SectionNode'):
|
||||
wine_color_name = transform_into_readable_str(wine_color_name)
|
||||
wine_color_name = transform_into_section_name(wine_color_name)
|
||||
|
||||
wine_color_section, _ = GuideWineColorSection.objects.get_or_create(
|
||||
name=wine_color_name,
|
||||
|
|
@ -972,6 +1002,14 @@ class GuideElementQuerySet(models.QuerySet):
|
|||
"""Return QuerySet with descendants."""
|
||||
return self.exclude(guide_element_type__name='Root')
|
||||
|
||||
def by_establishment_type(self, establishment_type_index_name: str):
|
||||
"""Return QuerySet by establishment_type."""
|
||||
return self.filter(
|
||||
guide_element_type__name__iexact=transform_into_section_name(
|
||||
establishment_type_index_name
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class GuideElement(ProjectBaseMixin, MPTTModel):
|
||||
"""Frozen state of elements of guide instance."""
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@
|
|||
import logging
|
||||
|
||||
from celery import shared_task
|
||||
from utils.methods import transform_into_readable_str
|
||||
|
||||
from utils.methods import transform_into_section_name
|
||||
|
||||
logging.basicConfig(format='[%(levelname)s] %(message)s', level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -31,7 +32,7 @@ def get_additional_product_data(section_node, product):
|
|||
@shared_task
|
||||
def generate_establishment_guide_elements(guide_id: int, filter_set: dict):
|
||||
"""Generate guide elements."""
|
||||
from collection.models import GuideElement, Guide
|
||||
from collection.models import Guide
|
||||
from establishment.models import Establishment
|
||||
|
||||
guide = Guide.objects.get(id=guide_id)
|
||||
|
|
@ -39,35 +40,53 @@ def generate_establishment_guide_elements(guide_id: int, filter_set: dict):
|
|||
queryset_values = Establishment.objects.filter(**filter_set).values()
|
||||
try:
|
||||
for instance in queryset_values:
|
||||
establishment_id = instance.get('id')
|
||||
establishment_qs = Establishment.objects.filter(id=establishment_id)
|
||||
if establishment_qs.exists():
|
||||
establishment = establishment_qs.first()
|
||||
root_node, _ = GuideElement.objects.get_or_create_root_node(guide_id)
|
||||
if root_node:
|
||||
city_node, _ = GuideElement.objects.get_or_create_city_node(root_node.id,
|
||||
establishment.address.city_id)
|
||||
if city_node:
|
||||
section_node, _ = GuideElement.objects.get_or_create_establishment_section_node(
|
||||
city_node.id,
|
||||
transform_into_readable_str(establishment.establishment_type.index_name),
|
||||
)
|
||||
if section_node:
|
||||
GuideElement.objects.get_or_create_establishment_node(
|
||||
*get_additional_establishment_data(section_node=section_node,
|
||||
establishment=establishment))
|
||||
else:
|
||||
logger.error(
|
||||
f'METHOD_NAME: {generate_establishment_guide_elements.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - SectionNode is not exists.')
|
||||
populate_establishment_guide(guide_id, instance.get('id'))
|
||||
except Exception as e:
|
||||
guide.change_state(Guide.WAITING)
|
||||
logger.error(f'METHOD_NAME: {generate_establishment_guide_elements.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - {e}')
|
||||
else:
|
||||
guide.update_count_related_objects()
|
||||
guide.change_state(Guide.BUILT)
|
||||
|
||||
|
||||
@shared_task
|
||||
def populate_establishment_guide(guide_id: int, establishment_id: int):
|
||||
"""Extend guide."""
|
||||
from collection.models import GuideElement, Guide
|
||||
from establishment.models import Establishment
|
||||
|
||||
guide = Guide.objects.get(id=guide_id)
|
||||
guide.change_state(Guide.BUILDING)
|
||||
try:
|
||||
establishment_qs = Establishment.objects.filter(id=establishment_id)
|
||||
if establishment_qs.exists():
|
||||
establishment = establishment_qs.first()
|
||||
root_node, _ = GuideElement.objects.get_or_create_root_node(guide_id)
|
||||
if root_node:
|
||||
city_node, _ = GuideElement.objects.get_or_create_city_node(root_node.id,
|
||||
establishment.address.city_id)
|
||||
if city_node:
|
||||
section_node, _ = GuideElement.objects.get_or_create_establishment_section_node(
|
||||
city_node.id,
|
||||
transform_into_section_name(establishment.establishment_type.index_name),
|
||||
)
|
||||
if section_node:
|
||||
GuideElement.objects.get_or_create_establishment_node(
|
||||
*get_additional_establishment_data(section_node=section_node,
|
||||
establishment=establishment))
|
||||
else:
|
||||
logger.error(f'METHOD_NAME: {generate_establishment_guide_elements.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - CityNode is not exists.')
|
||||
logger.error(
|
||||
f'METHOD_NAME: {generate_establishment_guide_elements.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - SectionNode is not exists.')
|
||||
else:
|
||||
logger.error(f'METHOD_NAME: {generate_establishment_guide_elements.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - RootNode is not exists.')
|
||||
f'DETAIL: Guide ID {guide_id} - CityNode is not exists.')
|
||||
else:
|
||||
logger.error(f'METHOD_NAME: {generate_establishment_guide_elements.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - RootNode is not exists.')
|
||||
else:
|
||||
logger.error(f'METHOD_NAME: {generate_establishment_guide_elements.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - Establishment {establishment_id} id is not exists.')
|
||||
except Exception as e:
|
||||
guide.change_state(Guide.WAITING)
|
||||
|
|
@ -78,6 +97,42 @@ def generate_establishment_guide_elements(guide_id: int, filter_set: dict):
|
|||
guide.change_state(Guide.BUILT)
|
||||
|
||||
|
||||
@shared_task
|
||||
def remove_establishment_guide(guide_id: int, establishment_id: int):
|
||||
"""Extend guide."""
|
||||
from collection.models import GuideElement, Guide
|
||||
from establishment.models import Establishment
|
||||
|
||||
guide = Guide.objects.get(id=guide_id)
|
||||
guide.change_state(Guide.REMOVING)
|
||||
try:
|
||||
establishment_qs = Establishment.objects.filter(id=establishment_id)
|
||||
if establishment_qs.exists():
|
||||
establishment = establishment_qs.first()
|
||||
if hasattr(establishment, 'establishment_type') and establishment.establishment_type.index_name:
|
||||
establishment_node_qs = GuideElement.objects.filter(establishment=establishment,
|
||||
guide=guide)
|
||||
if establishment_node_qs.exists():
|
||||
establishment_node_qs.first().delete()
|
||||
else:
|
||||
logger.error(f'METHOD_NAME: {remove_establishment_guide.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - EstablishmentNode {establishment_id} id is not exists.')
|
||||
else:
|
||||
logger.error(f'METHOD_NAME: {remove_establishment_guide.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - Establishment {establishment_id} '
|
||||
f'has not establishment type or establishment type index name.')
|
||||
else:
|
||||
logger.error(f'METHOD_NAME: {remove_establishment_guide.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - Establishment {establishment_id} id is not exists.')
|
||||
except Exception as e:
|
||||
guide.change_state(Guide.WAITING)
|
||||
logger.error(f'METHOD_NAME: {remove_establishment_guide.__name__}\n'
|
||||
f'DETAIL: Guide ID {guide_id} - {e}')
|
||||
else:
|
||||
guide.update_count_related_objects()
|
||||
guide.change_state(Guide.BUILT)
|
||||
|
||||
|
||||
@shared_task
|
||||
def generate_product_guide_elements(guide_id: int, filter_set: dict):
|
||||
"""Generate guide elements."""
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from django.utils.translation import gettext_lazy as _
|
|||
from rest_framework import serializers
|
||||
|
||||
from account.serializers.common import UserShortSerializer
|
||||
from collection.models import Guide
|
||||
from establishment import models, serializers as model_serializers
|
||||
from establishment.models import ContactEmail, ContactPhone, EstablishmentEmployee
|
||||
from gallery.models import Image
|
||||
|
|
@ -582,6 +583,17 @@ class EstablishmentAdminListSerializer(UserShortSerializer):
|
|||
]
|
||||
|
||||
|
||||
class EstablishmentGuideSerializer(serializers.ModelSerializer):
|
||||
"""Serializer for model Guide. """
|
||||
|
||||
class Meta:
|
||||
"""Meta class."""
|
||||
model = Guide
|
||||
fields = [
|
||||
'id',
|
||||
]
|
||||
|
||||
|
||||
class EstablishmentEmployeePositionsSerializer(serializers.ModelSerializer):
|
||||
"""Establishments from employee serializer"""
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ urlpatterns = [
|
|||
name='note-rud'),
|
||||
path('slug/<slug:slug>/admin/', views.EstablishmentAdminView.as_view(),
|
||||
name='establishment-admin-list'),
|
||||
path('slug/<slug:slug>/guides/<int:guide_id>/', views.EstablishmentGuideCreateDestroyView.as_view(),
|
||||
name='guide-list-create'),
|
||||
path('menus/dishes/', views.MenuDishesListCreateView.as_view(), name='menu-dishes-list'),
|
||||
path('menus/dishes/<int:pk>/', views.MenuDishesRUDView.as_view(), name='menu-dishes-rud'),
|
||||
path('menus/dishes/<int:pk>/gallery/', views.MenuGalleryListView.as_view(), name='menu-dishes-gallery-list'),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"""Establishment app views."""
|
||||
from django.db.models.query_utils import Q
|
||||
from django.db import transaction
|
||||
from django.db.models.query_utils import Q
|
||||
from django.http import Http404
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
|
|
@ -8,6 +8,7 @@ from rest_framework import generics, response, status
|
|||
from rest_framework.response import Response
|
||||
|
||||
from account.models import User
|
||||
from collection.models import Guide
|
||||
from establishment import filters, models, serializers
|
||||
from establishment.models import EstablishmentEmployee, Menu
|
||||
from timetable.models import Timetable
|
||||
|
|
@ -616,6 +617,82 @@ class EstablishmentAdminView(generics.ListAPIView):
|
|||
return User.objects.establishment_admin(establishment).distinct()
|
||||
|
||||
|
||||
class EstablishmentGuideCreateDestroyView(generics.GenericAPIView):
|
||||
"""Add/Remove establishment from guide."""
|
||||
establishment_lookup_url_kwarg = 'slug'
|
||||
guide_lookup_url_kwarg = 'guide_id'
|
||||
permission_classes = get_permission_classes(
|
||||
IsEstablishmentManager,
|
||||
IsEstablishmentAdministrator
|
||||
)
|
||||
|
||||
def get_establishment_queryset(self):
|
||||
"""Get Establishment queryset."""
|
||||
return EstablishmentMixinViews.get_queryset(self)
|
||||
|
||||
def get_guide_queryset(self):
|
||||
"""Get Guide queryset."""
|
||||
queryset = Guide.objects
|
||||
if hasattr(self, 'request') and hasattr(self.request, 'country_code'):
|
||||
return queryset.by_country_code(self.request.country_code)
|
||||
return queryset.none()
|
||||
|
||||
def get_establishment(self):
|
||||
queryset = self.get_establishment_queryset()
|
||||
|
||||
# Perform the lookup filtering.
|
||||
lookup_url_kwarg = getattr(self, 'establishment_lookup_url_kwarg', None)
|
||||
|
||||
assert lookup_url_kwarg and lookup_url_kwarg in self.kwargs, (
|
||||
'Expected view %s to be called with a URL keyword argument '
|
||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||
'attribute on the view correctly.' %
|
||||
(self.__class__.__name__, lookup_url_kwarg)
|
||||
)
|
||||
|
||||
filters = {'klass': queryset, lookup_url_kwarg: self.kwargs.get(lookup_url_kwarg)}
|
||||
obj = get_object_or_404(**filters)
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, obj)
|
||||
|
||||
return obj
|
||||
|
||||
def get_guide(self):
|
||||
queryset = self.get_guide_queryset()
|
||||
|
||||
# Perform the lookup filtering.
|
||||
lookup_url_kwarg = getattr(self, 'guide_lookup_url_kwarg', None)
|
||||
|
||||
assert lookup_url_kwarg and lookup_url_kwarg in self.kwargs, (
|
||||
'Expected view %s to be called with a URL keyword argument '
|
||||
'named "%s". Fix your URL conf, or set the `.lookup_field` '
|
||||
'attribute on the view correctly.' %
|
||||
(self.__class__.__name__, lookup_url_kwarg)
|
||||
)
|
||||
|
||||
obj = get_object_or_404(klass=queryset, id=self.kwargs.get(lookup_url_kwarg))
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, obj)
|
||||
|
||||
return obj
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""Implement GET-method."""
|
||||
establishment = self.get_establishment()
|
||||
guide = self.get_guide()
|
||||
guide.extend_establishment_guide(establishment.id)
|
||||
return Response(status=status.HTTP_200_OK)
|
||||
|
||||
def delete(self, request, *args, **kwargs):
|
||||
"""Implement DELETE-method."""
|
||||
establishment = self.get_establishment()
|
||||
guide = self.get_guide()
|
||||
guide.remove_establishment(establishment.id)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
class MenuDishesListCreateView(generics.ListCreateAPIView):
|
||||
"""Menu (dessert, main_course, starter) list create view."""
|
||||
serializer_class = serializers.MenuDishesSerializer
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
"""Utils app method."""
|
||||
import logging
|
||||
import pathlib
|
||||
import random
|
||||
import re
|
||||
import string
|
||||
from collections import namedtuple
|
||||
from functools import reduce
|
||||
from io import BytesIO
|
||||
import pathlib
|
||||
|
||||
import requests
|
||||
from PIL import Image
|
||||
from django.conf import settings
|
||||
|
|
@ -169,11 +170,11 @@ def dictfetchall(cursor):
|
|||
]
|
||||
|
||||
|
||||
def transform_into_readable_str(raw_string: str, postfix: str = 'SectionNode'):
|
||||
def transform_into_readable_str(raw_string: str):
|
||||
"""
|
||||
Transform slug into section name, i.e:
|
||||
like
|
||||
"EffervescentRoseDeSaigneeSectionNode"
|
||||
"EffervescentRoseDeSaignee"
|
||||
from
|
||||
"effervescent-rose-de-saignee"
|
||||
"""
|
||||
|
|
@ -183,6 +184,17 @@ def transform_into_readable_str(raw_string: str, postfix: str = 'SectionNode'):
|
|||
return f"{''.join([i.capitalize() for i in result])}"
|
||||
|
||||
|
||||
def transform_into_section_name(raw_string: str, postfix: str = 'SectionNode'):
|
||||
"""
|
||||
Transform slug into section name, i.e:
|
||||
like
|
||||
"EffervescentRoseDeSaigneeSectionNode"
|
||||
from
|
||||
"effervescent-rose-de-saignee"
|
||||
"""
|
||||
return f'{transform_into_readable_str(raw_string)}{postfix}'
|
||||
|
||||
|
||||
def transform_camelcase_to_underscore(raw_string: str):
|
||||
"""
|
||||
Transform str, i.e:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user