diff --git a/apps/establishment/models.py b/apps/establishment/models.py index c813ad74..e45cba77 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -17,7 +17,6 @@ from django.core.exceptions import ValidationError from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models from django.db.models import Case, ExpressionWrapper, F, Prefetch, Q, Subquery, When -from django.shortcuts import get_object_or_404 from django.utils import timezone from django.utils.translation import gettext_lazy as _ from phonenumber_field.modelfields import PhoneNumberField @@ -1145,7 +1144,7 @@ class EmployeeQuerySet(models.QuerySet): queryset=EstablishmentEmployee.objects.actual() .prefetch_related('establishment', 'position').order_by('-from_date'), to_attr='prefetched_establishment_employee'), - 'awards' + Prefetch('awards', queryset=Award.objects.select_related('award_type')) ) diff --git a/apps/establishment/serializers/back.py b/apps/establishment/serializers/back.py index 71147bbe..32784875 100644 --- a/apps/establishment/serializers/back.py +++ b/apps/establishment/serializers/back.py @@ -1,5 +1,6 @@ from functools import lru_cache +from django.contrib.contenttypes.models import ContentType from django.db.models import F from django.shortcuts import get_object_or_404 from django.utils.translation import gettext_lazy as _ @@ -15,6 +16,7 @@ from establishment.models import ContactEmail, ContactPhone, EstablishmentEmploy from establishment.serializers.common import ContactPhonesSerializer from gallery.models import Image from location.serializers import AddressDetailSerializer, TranslatedField, AddressBaseSerializer +from main import models as main_models from main.models import Currency from main.serializers import AwardSerializer from tag.serializers import TagBaseSerializer @@ -22,8 +24,6 @@ from utils.decorators import with_base_attributes from utils.methods import string_random from utils.serializers import ImageBaseSerializer, ProjectModelSerializer, TimeZoneChoiceField, \ PhoneMixinSerializer -from main import models as main_models -from django.contrib.contenttypes.models import ContentType def phones_handler(phones_list, establishment): @@ -363,7 +363,10 @@ class EmployeeBackSerializers(PhoneMixinSerializer, serializers.ModelSerializer) @staticmethod @lru_cache(maxsize=32) def get_qs(obj): - return obj.establishmentemployee_set.actual().annotate( + return obj.establishmentemployee_set.actual().only( + 'establishment', + 'from_date', + ).annotate( public_mark=F('establishment__public_mark'), est_id=F('establishment__id'), est_slug=F('establishment__slug'), diff --git a/apps/establishment/views/back.py b/apps/establishment/views/back.py index b061bef7..4fd42271 100644 --- a/apps/establishment/views/back.py +++ b/apps/establishment/views/back.py @@ -501,7 +501,7 @@ class EmployeeListCreateView(generics.ListCreateAPIView): * position_id (`int`) - filter by employees position identifier * public_mark (`str`) - filter by establishment public mark * toque_number (`str`) - filter by establishment toque number - * username (`str`) - filter by username or name + * username (`str`) - filter by a username or name #### Response ``` @@ -540,7 +540,7 @@ class EmployeeListCreateView(generics.ListCreateAPIView): * sex (`int`) - enum: `0 (Male), 1 (Female)` * birth_date (`str`) - birth datetime (datetime in a format `ISO-8601`) * email (`str`) - email address - * phone (`str`) - phone number in format `E164` + * phone (`str`) - phone number in a format `E164` * photo_id (`int`) - photo identifier """ filter_class = filters.EmployeeBackFilter @@ -553,11 +553,36 @@ class EmployeeListCreateView(generics.ListCreateAPIView): class EmployeesListSearchViews(generics.ListAPIView): - """Employee search view""" + """ + ## Employee search view. + ### *GET* + ##### Description + Return a non-paginated list of employees. + Available filters: + * search (`str`) - filter by name or last name with mistakes + * position_id (`int`) - filter by employees position identifier + * public_mark (`str`) - filter by establishment public mark + * toque_number (`str`) - filter by establishment toque number + * username (`str`) - filter by a username or name + (with limitations by the minimum number of characters) + + ###### Response + ``` + [ + { + "id": 1, + ... + } + ] + ``` + """ pagination_class = None - queryset = models.Employee.objects.all().with_back_office_related().select_related('photo') filter_class = filters.EmployeeBackSearchFilter serializer_class = serializers.EmployeeBackSerializers + queryset = ( + models.Employee.objects.with_back_office_related() + .select_related('photo') + ) permission_classes = get_permission_classes( IsEstablishmentManager, IsEstablishmentAdministrator, @@ -565,7 +590,7 @@ class EmployeesListSearchViews(generics.ListAPIView): class EstablishmentEmployeeListView(generics.ListCreateAPIView): - """Establishment emplyoees list view.""" + """Establishment employees list view.""" serializer_class = serializers.EstEmployeeBackSerializer pagination_class = None permission_classes = get_permission_classes( @@ -585,7 +610,50 @@ class EstablishmentEmployeeListView(generics.ListCreateAPIView): class EmployeeRUDView(generics.RetrieveUpdateDestroyAPIView): - """Employee RUD view.""" + """ + ## Employee Retrieve/Update/Destroy view + ### *GET* + #### Retrieve a serialized object of employee. + ##### Response + ``` + { + "id": 1, + ... + } + ``` + + ### *PUT*/*PATCH* + #### Description + Completely/Partially update an employee object. + ##### Request + Available fields: + * name (`str`) - employee name + * last_name (`str`) - employee last name + * sex (`enum`) - 0 (Male), 1 (Female) + * birth_date (`str`) - datetime in a format `ISO-8601` + * email (`str`) - employee email address + * phone (`str`) - phone number in E164 format + * toque_number (`int`) - employee toque number + * available_for_events (`bool`) - flag that responds for availability for events + * photo_id (`int`) - image identifier + ##### Response + Return an employee serialized object + I.e.: + ``` + { + "id": 1, + ... + } + ``` + + ### *DELETE* + #### Description + Delete an instance of employee + ##### Response + ``` + No response data + ``` + """ serializer_class = serializers.EmployeeBackSerializers queryset = models.Employee.objects.with_back_office_related() permission_classes = get_permission_classes( diff --git a/apps/utils/models.py b/apps/utils/models.py index eeb52c31..2f2a39d1 100644 --- a/apps/utils/models.py +++ b/apps/utils/models.py @@ -11,6 +11,7 @@ from django.contrib.postgres.fields.jsonb import KeyTextTransform from django.core.validators import FileExtensionValidator from django.shortcuts import get_object_or_404 from django.utils import timezone +from django.utils.functional import cached_property from django.utils.html import mark_safe from django.utils.translation import ugettext_lazy as _, get_language from easy_thumbnails.fields import ThumbnailerImageField @@ -516,13 +517,13 @@ def default_menu_bool_array(): class PhoneModelMixin: """Mixin for PhoneNumberField.""" - @property + @cached_property def country_calling_code(self): """Return phone code from PhonеNumberField.""" if hasattr(self, 'phone') and self.phone: return f'+{self.phone.country_code}' - @property + @cached_property def national_calling_number(self): """Return phone national number from from PhonеNumberField.""" if hasattr(self, 'phone') and (self.phone and hasattr(self.phone, 'national_number')):