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 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): class Role(ProjectBaseMixin):
"""Base Role model.""" """Base Role model."""
STANDARD_USER = 1 STANDARD_USER = 1
@ -44,12 +57,12 @@ class Role(ProjectBaseMixin):
(CONTENT_PAGE_MANAGER, _('Content page manager')), (CONTENT_PAGE_MANAGER, _('Content page manager')),
(ESTABLISHMENT_MANAGER, _('Establishment manager')), (ESTABLISHMENT_MANAGER, _('Establishment manager')),
(REVIEWER_MANGER, _('Reviewer manager')), (REVIEWER_MANGER, _('Reviewer manager')),
(RESTAURANT_REVIEWER, 'Restaurant reviewer'), (RESTAURANT_REVIEWER, _('Restaurant reviewer')),
(SALES_MAN, 'Sales man'), (SALES_MAN, _('Sales man')),
(WINERY_REVIEWER, 'Winery reviewer'), (WINERY_REVIEWER, _('Winery reviewer')),
(SELLER, 'Seller'), (SELLER, _('Seller')),
(LIQUOR_REVIEWER, 'Liquor reviewer'), (LIQUOR_REVIEWER, _('Liquor reviewer')),
(PRODUCT_REVIEWER, 'Product reviewer'), (PRODUCT_REVIEWER, _('Product reviewer')),
) )
role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES, role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES,
@ -67,6 +80,22 @@ class Role(ProjectBaseMixin):
help_text='navigation bar item permission', help_text='navigation bar item permission',
verbose_name=_('navigation bar 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): class UserManager(BaseUserManager):
"""Extended manager for User model.""" """Extended manager for User model."""
@ -347,6 +376,14 @@ class User(AbstractUser):
return set(result) 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): class UserRole(ProjectBaseMixin):
"""UserRole model.""" """UserRole model."""
VALIDATED = 'validated' VALIDATED = 'validated'
@ -377,6 +414,8 @@ class UserRole(ProjectBaseMixin):
help_text='A user (REQUESTER) who requests a ' help_text='A user (REQUESTER) who requests a '
'role change for a USER') 'role change for a USER')
objects = UserRoleQueryset.as_manager()
class Meta: class Meta:
unique_together = ['user', 'role', 'establishment', 'state'] unique_together = ['user', 'role', 'establishment', 'state']

View File

@ -148,3 +148,9 @@ class UserRoleSerializer(serializers.ModelSerializer):
'user', 'user',
'establishment' '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 = [ urlpatterns = [
path('role/', views.RoleListView.as_view(), name='role-list-create'), 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-role/', views.UserRoleListView.as_view(), name='user-role-list-create'),
path('user/', views.UserListView.as_view(), name='user-create-list'), path('user/', views.UserListView.as_view(), name='user-create-list'),
path('user/<int:id>/', views.UserRUDView.as_view(), name='user-rud'), 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 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 from rest_framework.filters import OrderingFilter
import csv import csv
from django.http import HttpResponse, HttpResponseNotFound from django.http import HttpResponse, HttpResponseNotFound
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
from account import models from account import models, filters
from account.models import User from account.models import User
from account.serializers import back as serializers from account.serializers import back as serializers
from account.serializers.common import RoleBaseSerializer from account.serializers.common import RoleBaseSerializer
@ -16,6 +17,34 @@ class RoleListView(generics.ListCreateAPIView):
queryset = models.Role.objects.all() 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): class UserRoleListView(generics.ListCreateAPIView):
serializer_class = serializers.UserRoleSerializer serializer_class = serializers.UserRoleSerializer
queryset = models.UserRole.objects.all() queryset = models.UserRole.objects.all()
@ -26,21 +55,14 @@ class UserListView(generics.ListCreateAPIView):
queryset = User.objects.prefetch_related('roles') queryset = User.objects.prefetch_related('roles')
serializer_class = serializers.BackUserSerializer serializer_class = serializers.BackUserSerializer
permission_classes = (permissions.IsAdminUser,) 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 = ( ordering_fields = (
'email_confirmed', 'email_confirmed',
'is_staff', 'is_staff',
'is_active', 'is_active',
'is_superuser', 'is_superuser',
'roles',
'last_login', 'last_login',
'date_joined', 'date_joined',
) )

View File

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