Skip to content

Commit

Permalink
feat : offers
Browse files Browse the repository at this point in the history
  • Loading branch information
qwejid committed Apr 5, 2024
1 parent 506ec44 commit 972e933
Show file tree
Hide file tree
Showing 34 changed files with 1,381 additions and 61 deletions.
Empty file removed api/migrations/__init__.py
Empty file.
4 changes: 2 additions & 2 deletions breaks/views/dicts.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
list=extend_schema(summary='Список статусов смен', tags=['Словари'])
)
class ReplacementStatusView(DictListMixin):
queryset = ReplacementStatus.objects.filter(is_active=True)
model = ReplacementStatus


@extend_schema_view(
list=extend_schema(summary='Список статусов обеденных перерывов', tags=['Словари'])
)
class BreakStatusView(DictListMixin):
queryset = BreakStatus.objects.filter(is_active=True)
model = BreakStatus

2 changes: 2 additions & 0 deletions common/constants/roles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PUBLIC_GROUP = 'public'
ADMIN_GROUP = 'admin'
Empty file removed common/migrations/__init__.py
Empty file.
34 changes: 33 additions & 1 deletion common/serializers/mixins.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
from rest_framework import serializers

from users.serializers.nested.users import UserShortSerializer
from rest_framework.generics import get_object_or_404

class ExtendedModelSerializer(serializers.ModelSerializer):
class Meta:
abstract = True

def get_from_url(self, lookup_field):
assert 'view' in self.context, (
'No view context in "%s". '
'Check parameter context on function calling.' % self.__class__.__name__
)

assert self.context['view'].kwargs.get(lookup_field), (
'Got no data from url in "%s". '
'Check lookup field on function calling.'
)
value = self.context['view'].kwargs.get(lookup_field)
return value

def get_object_from_url(self, model, lookup_field='pk', model_field='pk'):
obj_id = self.get_from_url(lookup_field)
obj = get_object_or_404(
queryset=model.objects.all(), **{model_field: obj_id}
)
return obj





class InfoModelSerializer(ExtendedModelSerializer):
created_by = UserShortSerializer()
updated_by = UserShortSerializer()

class Meta:
abstract = True

class DictMixinSerializer(serializers.Serializer):
code = serializers.CharField()
Expand Down
76 changes: 74 additions & 2 deletions common/views/mixins.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,99 @@
from rest_framework.viewsets import GenericViewSet
from rest_framework import mixins
from common.serializers.mixins import DictMixinSerializer
from common.constants import roles

class ExtendedGenericViewSet(GenericViewSet):
class ExtendedView:
multi_permission_classes = None
multi_serializer_class = None
request = None

def get_serializer_class(self):
assert self.serializer_class or self.multi_serializer_class, (
'"%s" should either include `serializer_class`,'
'`multi_serializer_class`, attributem, or override the '
'`get_serializer_class()` method.' % self.__class__.__name__
)
if not self.multi_serializer_class:
return self.serializer_class

user = self.request.user
if user.is_anonymous:
user_roles = (roles.PUBLIC_GROUP,)
elif user.is_superuser:
user_roles = (roles.ADMIN_GROUP,)
else:
user_roles = set(user.groups.all()).values_list('code', flat=True)

if hasattr(self, 'action') and self.action:
action = self.action
else:
action = self.request.method

# Trying to get role + action serializer
for role in user_roles:
serializer_key = f'{role}__{action}'
if self.multi_serializer_class.get(serializer_key):
return self.multi_serializer_class.get(serializer_key)

# Trying to get role serializer
for role in user_roles:
serializer_key = role
if self.multi_serializer_class.get(serializer_key):
return self.multi_serializer_class.get(serializer_key)

# Trying to get action serializer or default
return self.multi_serializer_class.get(action) or self.serializer_class

def get_permissions(self):
# define request action or method
if hasattr(self, 'action'):
action = self.action
else:
action = self.request.method

if self.multi_permission_classes:
permissions = self.multi_permission_classes.get(action)
if permissions:
return [permission() for permission in permissions]

return [permission() for permission in self.permission_classes]

class ExtendedGenericViewSet(ExtendedView, GenericViewSet):
pass

class ListViewSet(ExtendedGenericViewSet, mixins.ListModelMixin):
pass

class UpdateViewSet(ExtendedGenericViewSet, mixins.UpdateModelMixin):
pass

class DictListMixin(ListViewSet):
serializer_class = DictMixinSerializer
pagination_class = None
model = None

def get_queryset(self):
assert self.model, (
'"%s" should either include attribute `model`' % self.__class__.__name__
)
return self.model.objects.filter(is_active=True)


class CRUViewSet(ExtendedGenericViewSet,
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,):
pass

class CRUDViewSet(CRUViewSet,
mixins.DestroyModelMixin,):
pass

class ListCreateUpdateViewSet(ExtendedGenericViewSet,
mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.UpdateModelMixin,):
pass

15 changes: 13 additions & 2 deletions config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"rest_framework.permissions.IsAuthenticated",),

"DEFAULT_AUTHENTICATION_CLASSES": [
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.BasicAuthentication',
],

Expand All @@ -116,6 +117,7 @@
"rest_framework.parsers.FileUploadParser",
],

'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
"DEFAULT_SCHEMA_CLASS": 'drf_spectacular.openapi.AutoSchema',
"DEFAULT_PAGINATION_CLASS": "common.pagination.BasePagination",
}
Expand Down Expand Up @@ -183,12 +185,21 @@
'rest_framework.authentication.BasicAuthentication'],

"SWAGGER_UI_SETTINGS" : {
'DeepLinking' : True,
'DisplayOperationId' : True,
'deepLinking': True,
"displayOperationId": True,
"syntaxHighlight.active": True,
"syntaxHighlight.theme": "arta",
"defaultModelsExpandDepth": -1,
"displayRequestDuration": True,
"filter": True,
"requestSnippetsEnabled": True,
},

"COMPONENT_SPLIT_REQUEST" : True,
"SORT_OPERATIONS" : False,

'ENABLE_DJANGO_DEPLOY_CHECK': False,
'DISABLE_ERRORS_AND_WARNINGS': True,

}

Expand Down
28 changes: 20 additions & 8 deletions organisations/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib import admin
# from django.contrib.admin import TabularInline, StackedInline
from organisations.models import organisations, groups, dicts

from breaks.models.replacement import GroupInfo
from organisations.models import organisations, groups, dicts, offers

########################################################
# INLINES
Expand All @@ -10,9 +10,13 @@ class EmployeeInline(admin.TabularInline):
model = organisations.Employee
fields = ('user', 'position', 'date_joined',)

class OfferInline(admin.TabularInline):
model = offers.Offer
fields = ('org_accept', 'user', 'user_accept',)

class MemberInline(admin.TabularInline):
model = groups.Member
fields = ('user', 'date_joined',)
fields = ('employee', 'date_joined',)

class ProfileBreakInline(admin.StackedInline):
model = GroupInfo
Expand All @@ -35,8 +39,8 @@ class PositionAdmin(admin.ModelAdmin):
class OrganisationAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'director')
list_display_links = ('id', 'name',)
filter_horizontal = ('employees', )
inlines = (EmployeeInline,)
filter_vertical = ('employees',)
inlines = (EmployeeInline, OfferInline)
readonly_fields = (
'created_at', 'created_by', 'updated_at', 'updated_by',
)
Expand All @@ -46,10 +50,18 @@ class GroupAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'manager',)
list_display_links = ('id', 'name',)
search_fields = ("name",)
inlines = (MemberInline,
ProfileBreakInline,)
inlines = (
ProfileBreakInline,
MemberInline,
)
readonly_fields = (
'created_at', 'created_by', 'updated_at', 'updated_by',
)


@admin.register(offers.Offer)
class OffersAdmin(admin.ModelAdmin):
list_display = ('id', 'organisation', 'org_accept', 'user', 'user_accept',)
search_fields = ('organisation__name', 'user__last_name',)
readonly_fields = (
'created_at', 'created_by', 'updated_at', 'updated_by',
)
27 changes: 27 additions & 0 deletions organisations/backends.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from django.db.models import Q
from rest_framework.filters import BaseFilterBackend

#############################################################
# Пользовательская общая фильтрация
#############################################################

class OwnedByOrganisation(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
org_id = request.parser_context['kwargs'].get('pk')
return queryset.filter(organisation_id=org_id)


class MyOrganisation(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
user = request.user
return queryset.filter(
Q(director=user) | Q(employees=user)
)


class MyGroup(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
user = request.user
return queryset.filter(
Q(organisation__director=user) | Q(organisation__employees=user)
)
3 changes: 3 additions & 0 deletions organisations/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
DIRECTOR_POSITION = '1'
MANAGER_POSITION = '2'
OPERATOR_POSITION = '3'
Loading

0 comments on commit 972e933

Please sign in to comment.