fix role counter, added additional field role choice id

This commit is contained in:
Anatoly 2020-01-23 13:28:57 +03:00
parent a6f3384126
commit 587f6c0bad
4 changed files with 59 additions and 51 deletions

View File

@ -12,6 +12,7 @@ from django.utils.html import mark_safe
from django.utils.http import urlsafe_base64_encode
from django.utils.translation import ugettext_lazy as _
from rest_framework.authtoken.models import Token
from collections import Counter
from authorization.models import Application
from establishment.models import Establishment, EstablishmentSubType
@ -84,26 +85,13 @@ class Role(ProjectBaseMixin):
objects = RoleQuerySet.as_manager()
@classmethod
def role_names(cls):
return [role_name for role_name in dict(cls.ROLE_CHOICES).values()]
@classmethod
def role_types(cls):
roles = []
for role_id, role in dict(cls.ROLE_CHOICES).items():
roles.append({'id': role_id, 'name': role})
for role, display_name in dict(cls.ROLE_CHOICES).items():
roles.append({'role_name': role, 'role_counter': display_name, 'role': 0})
return roles
@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."""
@ -124,6 +112,14 @@ class UserManager(BaseUserManager):
class UserQuerySet(models.QuerySet):
"""Extended queryset for User model."""
def with_base_related(self):
"""Return QuerySet with base related."""
return self.select_related('last_country', 'last_country__country')
def with_extend_related(self):
"""Return QuerySet with extend related."""
return self.with_base_related().prefetch_related('roles', 'subscriber')
def active(self, switcher=True):
"""Filter only active users."""
return self.filter(is_active=switcher)
@ -403,10 +399,47 @@ class User(AbstractUser):
class UserRoleQueryset(models.QuerySet):
"""QuerySet for model UserRole."""
def _role_counter(self, country_code: str = None) -> dict:
additional_filters = {
'state': self.model.VALIDATED,
}
if country_code:
additional_filters.update({'role__site__country__code': country_code})
user_roles = (
self.filter(**additional_filters)
.distinct('user_id', 'role__role')
.values('user_id', 'role__role')
)
return dict(Counter([i['role__role'] for i in user_roles]))
def country_admin_role(self):
return self.filter(role__role=self.model.role.field.target_field.model.COUNTRY_ADMIN,
state=self.model.VALIDATED)
def aggregate_role_counter(self, country_code: str = None) -> list:
_role_choices = dict(Role.ROLE_CHOICES)
role_counter = []
# fill existed roles
for role, count in self._role_counter(country_code=country_code).items():
role_counter.append({
'role': role,
'role_name': _role_choices[role],
'count': count,
})
# check by roles
for role, role_name in _role_choices.items():
if role not in [i['role'] for i in role_counter]:
role_counter.append({
'role': role,
'role_name': _role_choices[role],
'count': 0,
})
return role_counter
class UserRole(ProjectBaseMixin):
"""UserRole model."""

View File

@ -143,9 +143,3 @@ 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,8 +7,7 @@ app_name = 'account'
urlpatterns = [
path('role/', views.RoleListView.as_view(), name='role-list-create'),
path('role/types/', views.RoleChoiceListView.as_view(), name='role-type-list'),
path('role/tab/', views.RoleTabRetrieveView.as_view(), name='role-tab'),
path('role/types/', views.RoleTypeRetrieveView.as_view(), name='role-types'),
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

@ -18,39 +18,18 @@ class RoleListView(generics.ListCreateAPIView):
filter_class = filters.RoleListFilter
class RoleChoiceListView(generics.GenericAPIView):
"""Return role choices."""
def get(self, request, *args, **kwargs):
"""Implement GET-method"""
return Response(models.Role.role_types(), status=status.HTTP_200_OK)
class RoleTabRetrieveView(generics.GenericAPIView):
class RoleTypeRetrieveView(generics.GenericAPIView):
permission_classes = [permissions.IsAdminUser]
def get_queryset(self):
"""Overridden get_queryset method."""
additional_filters = {}
def get(self, request, *args, **kwargs):
"""Implement GET-method"""
country_code = None
if (self.request.user.userrole_set.country_admin_role().exists() and
hasattr(self.request, 'country_code')):
additional_filters.update({'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_counter': 0})
country_code = self.request.country_code
data = models.UserRole.objects.aggregate_role_counter(country_code)
return Response(data, status=status.HTTP_200_OK)
@ -61,7 +40,6 @@ class UserRoleListView(generics.ListCreateAPIView):
class UserListView(generics.ListCreateAPIView):
"""User list create view."""
queryset = User.objects.prefetch_related('roles', 'subscriber')
serializer_class = serializers.BackUserSerializer
permission_classes = (permissions.IsAdminUser,)
filter_class = filters.AccountBackOfficeFilter
@ -76,6 +54,10 @@ class UserListView(generics.ListCreateAPIView):
'date_joined',
)
def get_queryset(self):
"""Overridden get_queryset method."""
return User.objects.with_extend_related()
class UserRUDView(generics.RetrieveUpdateDestroyAPIView):
"""User RUD view."""