Merge branch 'feature/fields_for_establishment' into 'develop'

Feature/fields for establishment

See merge request gm/gm-backend!268
This commit is contained in:
Олег Хаятов 2020-02-07 11:50:42 +00:00
commit 6868f75dc8
5 changed files with 109 additions and 18 deletions

View File

@ -0,0 +1,23 @@
# Generated by Django 2.2.7 on 2020-02-07 11:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('establishment', '0098_auto_20200204_1205'),
]
operations = [
migrations.AddField(
model_name='establishment',
name='last_update_by_gm',
field=models.DateTimeField(null=True),
),
migrations.AddField(
model_name='establishment',
name='last_update_by_manager',
field=models.DateTimeField(null=True),
),
]

View File

@ -33,7 +33,7 @@ from utils.models import (
BaseAttributes, FavoritesMixin, FileMixin, GalleryMixin, HasTagsMixin, BaseAttributes, FavoritesMixin, FileMixin, GalleryMixin, HasTagsMixin,
IntermediateGalleryModelMixin, ProjectBaseMixin, TJSONField, TranslatedFieldsMixin, IntermediateGalleryModelMixin, ProjectBaseMixin, TJSONField, TranslatedFieldsMixin,
TypeDefaultImageMixin, URLImageMixin, default_menu_bool_array, PhoneModelMixin, TypeDefaultImageMixin, URLImageMixin, default_menu_bool_array, PhoneModelMixin,
AwardsModelMixin) AwardsModelMixin, CarouselMixin, UpdateByMixin)
# todo: establishment type&subtypes check # todo: establishment type&subtypes check
@ -555,8 +555,15 @@ class EstablishmentQuerySet(models.QuerySet):
return self.prefetch_related('menu_set', 'menu_set__plates', 'back_office_wine') return self.prefetch_related('menu_set', 'menu_set__plates', 'back_office_wine')
class Establishment(GalleryMixin, ProjectBaseMixin, URLImageMixin, class Establishment(GalleryMixin,
TranslatedFieldsMixin, HasTagsMixin, FavoritesMixin, AwardsModelMixin): ProjectBaseMixin,
URLImageMixin,
TranslatedFieldsMixin,
HasTagsMixin,
FavoritesMixin,
AwardsModelMixin,
CarouselMixin,
UpdateByMixin):
"""Establishment model.""" """Establishment model."""
ABANDONED = 0 ABANDONED = 0
@ -725,9 +732,13 @@ class Establishment(GalleryMixin, ProjectBaseMixin, URLImageMixin,
raise ValidationError('Establishment type of subtype does not match') raise ValidationError('Establishment type of subtype does not match')
self.establishment_subtypes.add(establishment_subtype) self.establishment_subtypes.add(establishment_subtype)
@property
def last_review(self):
return self.reviews.by_status(Review.READY).last()
@property @property
def vintage_year(self): def vintage_year(self):
last_review = self.reviews.by_status(Review.READY).last() last_review = self.last_review
if last_review: if last_review:
return last_review.vintage return last_review.vintage

View File

@ -1,3 +1,4 @@
from datetime import datetime
from functools import lru_cache from functools import lru_cache
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -9,6 +10,7 @@ from rest_framework import serializers
from slugify import slugify from slugify import slugify
from account import models as account_models from account import models as account_models
from account.models import Role
from account.serializers.common import UserShortSerializer from account.serializers.common import UserShortSerializer
from collection.models import Guide from collection.models import Guide
from establishment import models, serializers as model_serializers from establishment import models, serializers as model_serializers
@ -21,6 +23,7 @@ from location.serializers import AddressDetailSerializer, TranslatedField, Addre
from main import models as main_models from main import models as main_models
from main.models import Currency from main.models import Currency
from main.serializers import AwardSerializer from main.serializers import AwardSerializer
from review.serializers import ReviewBaseSerializer, User
from tag.serializers import TagBaseSerializer from tag.serializers import TagBaseSerializer
from utils.decorators import with_base_attributes from utils.decorators import with_base_attributes
from utils.methods import string_random from utils.methods import string_random
@ -213,6 +216,7 @@ class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
subtypes = model_serializers.EstablishmentSubTypeBaseSerializer(source='establishment_subtypes', subtypes = model_serializers.EstablishmentSubTypeBaseSerializer(source='establishment_subtypes',
read_only=True, many=True) read_only=True, many=True)
type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True) type = model_serializers.EstablishmentTypeBaseSerializer(source='establishment_type', read_only=True)
phones = serializers.ListField( phones = serializers.ListField(
source='contact_phones', source='contact_phones',
allow_null=True, allow_null=True,
@ -221,8 +225,11 @@ class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
required=False, required=False,
write_only=True, write_only=True,
) )
contact_phones = ContactPhonesSerializer(source='phones', read_only=True, many=True) contact_phones = ContactPhonesSerializer(source='phones', read_only=True, many=True)
last_review = ReviewBaseSerializer(read_only=True)
class Meta(model_serializers.EstablishmentBaseSerializer.Meta): class Meta(model_serializers.EstablishmentBaseSerializer.Meta):
fields = [ fields = [
'id', 'id',
@ -251,6 +258,10 @@ class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
'tags', 'tags',
'status', 'status',
'status_display', 'status_display',
'last_review',
'must_of_the_week',
'last_update_by_gm',
'last_update_by_manager',
] ]
def to_representation(self, instance): def to_representation(self, instance):
@ -258,7 +269,7 @@ class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
data['phones'] = data.pop('contact_phones', None) data['phones'] = data.pop('contact_phones', None)
return data return data
def update(self, instance, validated_data): def update(self, instance: models.Establishment, validated_data):
phones_list = [] phones_list = []
if 'contact_phones' in validated_data: if 'contact_phones' in validated_data:
phones_list = validated_data.pop('contact_phones') phones_list = validated_data.pop('contact_phones')
@ -267,9 +278,30 @@ class EstablishmentRUDSerializer(model_serializers.EstablishmentBaseSerializer):
if 'contact_emails' in validated_data: if 'contact_emails' in validated_data:
emails_list = validated_data.pop('contact_emails') emails_list = validated_data.pop('contact_emails')
request = self.context.get('request')
if request and hasattr(request, 'user'):
user = request.user
if isinstance(user, User):
is_by_manager = user.userrole_set.filter(
pk=user.pk,
role__in=(
Role.ESTABLISHMENT_MANAGER,
Role.ESTABLISHMENT_ADMINISTRATOR,
Role.COUNTRY_ADMIN
)
).exists()
if is_by_manager:
instance.last_update_by_manager = datetime.now()
else:
''' by gm. '''
instance.last_update_by_gm = datetime.now()
instance = super().update(instance, validated_data) instance = super().update(instance, validated_data)
phones_handler(phones_list, instance) phones_handler(phones_list, instance)
emails_handler(emails_list, instance) emails_handler(emails_list, instance)
return instance return instance

View File

@ -22,7 +22,7 @@ from utils.models import (
BaseAttributes, FavoritesMixin, GalleryMixin, HasTagsMixin, IntermediateGalleryModelMixin, BaseAttributes, FavoritesMixin, GalleryMixin, HasTagsMixin, IntermediateGalleryModelMixin,
ProjectBaseMixin, ProjectBaseMixin,
TJSONField, TranslatedFieldsMixin, TypeDefaultImageMixin, TJSONField, TranslatedFieldsMixin, TypeDefaultImageMixin,
) CarouselMixin)
from utils.querysets import TranslationQuerysetMixin from utils.querysets import TranslationQuerysetMixin
@ -257,8 +257,12 @@ class NewsQuerySet(TranslationQuerysetMixin):
return self.filter(site__country__code=country_code) if not user.is_superuser else self return self.filter(site__country__code=country_code) if not user.is_superuser else self
class News(GalleryMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixin, class News(GalleryMixin,
FavoritesMixin): BaseAttributes,
TranslatedFieldsMixin,
HasTagsMixin,
FavoritesMixin,
CarouselMixin):
"""News model.""" """News model."""
STR_FIELD_NAME = 'title' STR_FIELD_NAME = 'title'
@ -366,16 +370,6 @@ class News(GalleryMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixin,
self.duplication_date = timezone.now() self.duplication_date = timezone.now()
self.save() self.save()
@property
def must_of_the_week(self) -> bool:
"""Detects whether current item in carousel"""
kwargs = {
'content_type': ContentType.objects.get_for_model(self),
'object_id': self.pk,
'country': self.country,
}
return Carousel.objects.filter(**kwargs).exists()
@property @property
def publication_datetime(self): def publication_datetime(self):
"""Represents datetime object combined from `publication_date` & `publication_time` fields""" """Represents datetime object combined from `publication_date` & `publication_time` fields"""

View File

@ -4,6 +4,7 @@ from os.path import exists
from django.conf import settings from django.conf import settings
from django.contrib.auth.tokens import PasswordResetTokenGenerator from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.contrib.contenttypes.models import ContentType
from django.contrib.gis.db import models from django.contrib.gis.db import models
from django.contrib.postgres.aggregates import ArrayAgg from django.contrib.postgres.aggregates import ArrayAgg
from django.contrib.postgres.fields import JSONField from django.contrib.postgres.fields import JSONField
@ -517,6 +518,7 @@ def default_menu_bool_array():
class PhoneModelMixin: class PhoneModelMixin:
"""Mixin for PhoneNumberField.""" """Mixin for PhoneNumberField."""
@cached_property @cached_property
def country_calling_code(self): def country_calling_code(self):
"""Return phone code from PhonеNumberField.""" """Return phone code from PhonеNumberField."""
@ -537,3 +539,32 @@ class AwardsModelMixin:
if hasattr(self, 'awards'): if hasattr(self, 'awards'):
self.awards.remove(award) self.awards.remove(award)
class CarouselMixin:
@property
def must_of_the_week(self) -> bool:
"""Detects whether current item in carousel"""
from main.models import Carousel
if hasattr(self, 'pk') and (hasattr(self, 'country') or hasattr(self, 'country_id')):
kwargs = {
'content_type': ContentType.objects.get_for_model(self),
'object_id': self.pk,
'country': getattr(self, 'country', getattr(self, 'country_id', None)),
}
return Carousel.objects.filter(**kwargs).exists()
return False
class UpdateByMixin(models.Model):
"""Modify by mixin"""
last_update_by_manager = models.DateTimeField(null=True)
last_update_by_gm = models.DateTimeField(null=True)
class Meta:
"""Meta class."""
abstract = True