added endpoint /api/back/account/role-tab/

This commit is contained in:
Anatoly 2020-01-17 17:38:50 +03:00
parent 0bb521b479
commit a26109a8da
6 changed files with 115 additions and 17 deletions

29
apps/account/filters.py Normal file
View File

@ -0,0 +1,29 @@
"""Account app filters."""
from django.core.validators import EMPTY_VALUES
from django_filters import rest_framework as filters
from account import models
class AccountBackOfficeFilter(filters.FilterSet):
"""Account filter set."""
role = filters.MultipleChoiceFilter(choices=models.Role.ROLE_CHOICES,
method='filter_by_roles')
class Meta:
"""Meta class."""
model = models.User
fields = (
'role',
'email_confirmed',
'is_staff',
'is_active',
'is_superuser',
)
def filter_by_roles(self, queryset, name, value):
if value not in EMPTY_VALUES:
return queryset.by_roles(value)
return queryset

View File

@ -22,6 +22,19 @@ from utils.models import ImageMixin, ProjectBaseMixin, PlatformMixin
from utils.tokens import GMRefreshToken
class RoleQuerySet(models.QuerySet):
def annotate_role_name(self):
return self.annotate(role_name=models.Case(*self.model.role_condition_expressions(),
output_field=models.CharField()))
def annotate_role_counter(self):
return self.annotate(
role_counter=models.Count('userrole',
distinct=True,
filter=models.Q(userrole__state=UserRole.VALIDATED)))
class Role(ProjectBaseMixin):
"""Base Role model."""
STANDARD_USER = 1
@ -44,12 +57,12 @@ class Role(ProjectBaseMixin):
(CONTENT_PAGE_MANAGER, _('Content page manager')),
(ESTABLISHMENT_MANAGER, _('Establishment manager')),
(REVIEWER_MANGER, _('Reviewer manager')),
(RESTAURANT_REVIEWER, 'Restaurant reviewer'),
(SALES_MAN, 'Sales man'),
(WINERY_REVIEWER, 'Winery reviewer'),
(SELLER, 'Seller'),
(LIQUOR_REVIEWER, 'Liquor reviewer'),
(PRODUCT_REVIEWER, 'Product reviewer'),
(RESTAURANT_REVIEWER, _('Restaurant reviewer')),
(SALES_MAN, _('Sales man')),
(WINERY_REVIEWER, _('Winery reviewer')),
(SELLER, _('Seller')),
(LIQUOR_REVIEWER, _('Liquor reviewer')),
(PRODUCT_REVIEWER, _('Product reviewer')),
)
role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES,
@ -67,6 +80,22 @@ class Role(ProjectBaseMixin):
help_text='navigation bar item permission',
verbose_name=_('navigation bar permission'))
objects = RoleQuerySet.as_manager()
@classmethod
def role_names(cls):
return [role_name._proxy____args[0]
for role_name in dict(cls.ROLE_CHOICES).values()]
@classmethod
def role_condition_expressions(cls) -> list:
role_choices = {role_id: role_name._proxy____args[0]
for role_id, role_name in dict(cls.ROLE_CHOICES).items()}
whens = [models.When(role=role_id, then=models.Value(role_name))
for role_id, role_name in role_choices.items()]
return whens
class UserManager(BaseUserManager):
"""Extended manager for User model."""
@ -347,6 +376,14 @@ class User(AbstractUser):
return set(result)
class UserRoleQueryset(models.QuerySet):
"""QuerySet for model UserRole."""
def country_admin_role(self):
return self.filter(role__role=self.model.role.field.target_field.model.COUNTRY_ADMIN,
state=self.model.VALIDATED)
class UserRole(ProjectBaseMixin):
"""UserRole model."""
VALIDATED = 'validated'
@ -377,6 +414,8 @@ class UserRole(ProjectBaseMixin):
help_text='A user (REQUESTER) who requests a '
'role change for a USER')
objects = UserRoleQueryset.as_manager()
class Meta:
unique_together = ['user', 'role', 'establishment', 'state']

View File

@ -148,3 +148,9 @@ class UserRoleSerializer(serializers.ModelSerializer):
'user',
'establishment'
]
class RoleTabRetrieveSerializer(serializers.Serializer):
"""Serializer for BackOffice role tab."""
role_name = serializers.CharField()
role_counter = serializers.IntegerField()

View File

@ -7,6 +7,7 @@ app_name = 'account'
urlpatterns = [
path('role/', views.RoleListView.as_view(), name='role-list-create'),
path('role-tab/', views.RoleTabRetrieveView.as_view(), name='role-tab'),
path('user-role/', views.UserRoleListView.as_view(), name='user-role-list-create'),
path('user/', views.UserListView.as_view(), name='user-create-list'),
path('user/<int:id>/', views.UserRUDView.as_view(), name='user-rud'),

View File

@ -1,11 +1,12 @@
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import generics, permissions
from rest_framework import generics, permissions, status
from rest_framework.response import Response
from rest_framework.filters import OrderingFilter
import csv
from django.http import HttpResponse, HttpResponseNotFound
from rest_framework.authtoken.models import Token
from account import models
from account import models, filters
from account.models import User
from account.serializers import back as serializers
from account.serializers.common import RoleBaseSerializer
@ -16,6 +17,34 @@ class RoleListView(generics.ListCreateAPIView):
queryset = models.Role.objects.all()
class RoleTabRetrieveView(generics.GenericAPIView):
permission_classes = [permissions.IsAdminUser]
def get_queryset(self):
"""Overridden get_queryset method."""
additional_filters = {}
if self.request.user.userrole_set.country_admin_role().exists():
additional_filters.update({'userrole__country__code': self.request.country_code})
return models.Role.objects.filter(**additional_filters)\
.annotate_role_name()\
.values('role_name')\
.annotate_role_counter()\
.values('role_name', 'role_counter')
def get(self, request, *args, **kwargs):
"""Implement GET-method"""
data = list(self.get_queryset())
# todo: Need refactoring. Extend data list with non-existed role.
for role in models.Role.role_names():
if role not in [role.get('role_name') for role in data]:
data.append({'role_name': role, 'role_number': 0})
return Response(data, status=status.HTTP_200_OK)
class UserRoleListView(generics.ListCreateAPIView):
serializer_class = serializers.UserRoleSerializer
queryset = models.UserRole.objects.all()
@ -26,21 +55,14 @@ class UserListView(generics.ListCreateAPIView):
queryset = User.objects.prefetch_related('roles')
serializer_class = serializers.BackUserSerializer
permission_classes = (permissions.IsAdminUser,)
filter_backends = (DjangoFilterBackend, OrderingFilter)
filter_class = filters.AccountBackOfficeFilter
filter_backends = (OrderingFilter, )
filterset_fields = (
'email_confirmed',
'is_staff',
'is_active',
'is_superuser',
'roles',
)
ordering_fields = (
'email_confirmed',
'is_staff',
'is_active',
'is_superuser',
'roles',
'last_login',
'date_joined',
)

View File

@ -5,6 +5,7 @@ from django.conf import settings
from tag import models
from product import models as product_models
class TagsBaseFilterSet(filters.FilterSet):
# Object type choices