diff --git a/core/apps/accounts/models/user.py b/core/apps/accounts/models/user.py index d6e375f..f24edda 100644 --- a/core/apps/accounts/models/user.py +++ b/core/apps/accounts/models/user.py @@ -3,6 +3,7 @@ from django.db import models from ..choices import RoleChoice from ..managers import UserManager +from ...evaluation.permissions.permission import Role class User(auth_models.AbstractUser): @@ -17,6 +18,7 @@ class User(auth_models.AbstractUser): default=RoleChoice.USER, ) avatar = models.ImageField(upload_to="avatars/", null=True, blank=True) + permission = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True) USERNAME_FIELD = "phone" objects = UserManager() diff --git a/core/apps/accounts/serializers/user.py b/core/apps/accounts/serializers/user.py index 2a3d902..9019962 100644 --- a/core/apps/accounts/serializers/user.py +++ b/core/apps/accounts/serializers/user.py @@ -42,4 +42,16 @@ class AdminUserSerializer(serializers.ModelSerializer): request = self.context.get('request') if obj.avatar: return request.build_absolute_uri(obj.avatar.url) - return None \ No newline at end of file + return None + + + +class UserCreateSerializer(serializers.ModelSerializer): + class Meta: + model = get_user_model() + fields = [ + "phone", + "first_name", + "last_name", + "password", + "role"] \ No newline at end of file diff --git a/core/apps/accounts/urls.py b/core/apps/accounts/urls.py index 45ae8fd..f2b21ff 100644 --- a/core/apps/accounts/urls.py +++ b/core/apps/accounts/urls.py @@ -4,7 +4,8 @@ Accounts app urls from django.urls import path, include from rest_framework_simplejwt import views as jwt_views -from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView, UserListApiView, AdminUserListApiView,AdminUserView +from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView, UserListApiView, AdminUserListApiView, \ + AdminUserView, AdminCreateAPIView, AdminUpdateAPIView from rest_framework.routers import DefaultRouter router = DefaultRouter() @@ -26,4 +27,6 @@ urlpatterns = [ ), path("user/list/", UserListApiView.as_view(), name="user-list"), path("admin-user/list/", AdminUserListApiView.as_view(), name="admin-user-list"), + path("admin/create/", AdminCreateAPIView.as_view(), name="user-create"), + path("admin/update/", AdminUpdateAPIView.as_view(), name="user-update"), ] diff --git a/core/apps/accounts/views/user.py b/core/apps/accounts/views/user.py index 73a1b1b..7a63242 100644 --- a/core/apps/accounts/views/user.py +++ b/core/apps/accounts/views/user.py @@ -1,18 +1,19 @@ from django.contrib.auth import get_user_model - +from django.shortcuts import get_object_or_404 +from django_core.mixins import BaseViewSetMixin +from drf_spectacular.utils import extend_schema from rest_framework import generics, filters from rest_framework.permissions import IsAuthenticated - -from drf_spectacular.utils import extend_schema - -from core.apps.accounts.serializers.user import UserSerializer, AdminUserSerializer -from core.apps.accounts.choices.user import RoleChoice -from django_core.mixins import BaseViewSetMixin +from rest_framework.response import Response +from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet +from core.apps.accounts.choices.user import RoleChoice +from core.apps.accounts.serializers.user import UserSerializer, AdminUserSerializer, UserCreateSerializer User = get_user_model() + @extend_schema(tags=['User']) class UserListApiView(generics.ListAPIView): queryset = User.objects.filter(role=RoleChoice.USER) @@ -32,9 +33,9 @@ class AdminUserListApiView(generics.ListAPIView): permission_classes = [IsAuthenticated] filter_backends = [filters.SearchFilter] search_fields = ['phone', 'first_name', 'last_name'] - -@extend_schema(tags=["User"],request=AdminUserSerializer) + +@extend_schema(tags=["User"], request=AdminUserSerializer) class AdminUserView(BaseViewSetMixin, ModelViewSet): queryset = User.objects.filter(role=RoleChoice.USER) serializer_class = AdminUserSerializer @@ -45,3 +46,37 @@ class AdminUserView(BaseViewSetMixin, ModelViewSet): def serializer_context(self): return self.serializer_class(context={"request": self.request}) + +@extend_schema(tags=['User'], + responses={200: UserSerializer}, + request=UserCreateSerializer) +class AdminCreateAPIView(APIView): + permission_classes = [IsAuthenticated] + + def post(self, request): + if request.user.role not in (RoleChoice.SUPERUSER, RoleChoice.ADMIN): + return Response({'detail': 'Forbidden'}, status=403) + + serializer = UserCreateSerializer(data=request.data) + serializer.is_valid(raise_exception=True) + serializer.save() + + return Response(serializer.data, status=201) + + +@extend_schema(tags=['User'], + responses={200: UserSerializer}, + request=UserCreateSerializer) +class AdminUpdateAPIView(APIView): + permission_classes = [IsAuthenticated] + + def put(self, request, pk): + if request.user.role not in (RoleChoice.SUPERUSER, RoleChoice.ADMIN): + return Response({'detail': 'Forbidden'}, status=403) + + user = get_object_or_404(User, pk=pk) + serializer = UserCreateSerializer(user, data=request.data) + serializer.is_valid(raise_exception=True) + serializer.save() + + return Response(serializer.data, status=200) diff --git a/core/apps/evaluation/models/auto.py b/core/apps/evaluation/models/auto.py index b0f9d4b..5a77af3 100644 --- a/core/apps/evaluation/models/auto.py +++ b/core/apps/evaluation/models/auto.py @@ -267,6 +267,12 @@ class AutoEvaluationModel(AbstractBaseModel): choices=AutoEvaluationStatus.choices, default=AutoEvaluationStatus.CREATED, ) + is_archived = models.BooleanField( + verbose_name=_("is archived"), + default=False, + ) + + def __str__(self): return f"Auto Evaluation {self.registration_number or self.pk}" diff --git a/core/apps/evaluation/permissions/permission.py b/core/apps/evaluation/permissions/permission.py new file mode 100644 index 0000000..3b305c2 --- /dev/null +++ b/core/apps/evaluation/permissions/permission.py @@ -0,0 +1,60 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ +from pydantic import BaseModel + + +class PermissionToAction(BaseModel): + name = models.CharField(max_length=200) + code = models.CharField(max_length=100, unique=True) + + def __str__(self): + return f"{self.name} - {self.code}" + + class Meta: + verbose_name = _('Harakatlar uchun ruxsatnoma') + verbose_name_plural = _('Harakatlar uchun ruxsatnomalar') + + +class PermissionToTab(BaseModel): + name = models.CharField(max_length=200) + code = models.CharField(max_length=100, unique=True) + permission_to_actions = models.ManyToManyField( + PermissionToAction, related_name='permission_to_tabs' + ) + + def __str__(self): + return f'{self.name} - {self.code}' + + class Meta: + verbose_name = _("Bo'lim uchun ruxsatnoma") + verbose_name_plural = _("Bo'lim uchun ruxsatnomalar") + + +class Permission(BaseModel): + name = models.CharField(max_length=200) + code = models.CharField(max_length=100, unique=True) + permission_tab = models.ManyToManyField(PermissionToTab, related_name='permissions') + + def __str__(self): + return f'{self.name} - {self.code}' + + class Meta: + verbose_name = _('Sahifa uchun ruxsatnoma') + verbose_name_plural = _('Sahifa uchun ruxsatnomalar') + +class Role(models.Model): + name = models.CharField(max_length=200, unique=True) + permissions = models.ManyToManyField(Permission, related_name='roles', blank=True) + permission_to_tabs = models.ManyToManyField(PermissionToTab, related_name='roles', blank=True) + permission_to_actions = models.ManyToManyField( + PermissionToAction, related_name='roles', blank=True + ) + comment = models.CharField(max_length=200, null=True, blank=True) + + def __str__(self): + return self.name + + class Meta: + verbose_name = _('Rol') + verbose_name_plural = _('Rollar') + diff --git a/core/apps/evaluation/serializers/auto/AutoEvaluation.py b/core/apps/evaluation/serializers/auto/AutoEvaluation.py index e3407de..137278f 100644 --- a/core/apps/evaluation/serializers/auto/AutoEvaluation.py +++ b/core/apps/evaluation/serializers/auto/AutoEvaluation.py @@ -1,18 +1,20 @@ import re -from django.contrib.auth import get_user_model +from django.contrib.auth import get_user_model from rest_framework import serializers -from core.apps.evaluation.models import AutoEvaluationModel,ReferenceitemModel, EvaluationrequestModel -from core.apps.evaluation.serializers.reference import ListReferenceitemSerializer from core.apps.evaluation.choices.request import RequestStatus +from core.apps.evaluation.models import AutoEvaluationModel, ReferenceitemModel, EvaluationrequestModel +from core.apps.evaluation.serializers.reference import ListReferenceitemSerializer User = get_user_model() + class BaseAutoevaluationSerializer(serializers.ModelSerializer): status_display = serializers.CharField(source="get_status_display", read_only=True) object_type_display = serializers.CharField(source="get_object_type_display", read_only=True, default=None) - object_owner_type_display = serializers.CharField(source="get_object_owner_type_display", read_only=True, default=None) + object_owner_type_display = serializers.CharField(source="get_object_owner_type_display", read_only=True, + default=None) rate_type = ListReferenceitemSerializer(read_only=True) value_determined = ListReferenceitemSerializer(read_only=True) property_rights = ListReferenceitemSerializer(read_only=True) @@ -72,6 +74,7 @@ class ListAutoevaluationSerializer(BaseAutoevaluationSerializer): class RetrieveAutoevaluationSerializer(BaseAutoevaluationSerializer): car_type_display = serializers.CharField(source="get_car_type_display", read_only=True, default=None) car_wheel_display = serializers.CharField(source="get_car_wheel_display", read_only=True, default=None) + # object_location_highways_display = serializers.CharField( # source="get_object_location_highways_display", read_only=True, default=None # ) @@ -141,7 +144,6 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer): allow_null=True, ) - class Meta: model = AutoEvaluationModel fields = [ @@ -222,6 +224,7 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer): return attrs + class CreateAutoevaluationSerializer(serializers.ModelSerializer): property_rights = serializers.PrimaryKeyRelatedField( queryset=ReferenceitemModel.objects.all(), @@ -254,7 +257,6 @@ class CreateAutoevaluationSerializer(serializers.ModelSerializer): allow_null=True, ) - class Meta: model = AutoEvaluationModel fields = [ @@ -356,3 +358,13 @@ class AutoEvaluationAppraisersSerializer(serializers.Serializer): raise serializers.ValidationError("Invalid appraisers IDs.") data['users'] = users return data + +class AutoEvaluationSerializer(serializers.Serializer): + brand = serializers.CharField() + brand_model = serializers.CharField() + year = serializers.CharField() + color = serializers.CharField() + transmission = serializers.CharField() + condition = serializers.CharField() + fuel_type = serializers.CharField() + mileage = serializers.CharField() \ No newline at end of file diff --git a/core/apps/evaluation/urls.py b/core/apps/evaluation/urls.py index c27c9b0..1c93b06 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -31,7 +31,7 @@ from .views import ( EvaluationStatusChange, CertificateView, ArchiveQuickEvaluationView, - ArchiveEvaluationrequestView, + ArchiveEvaluationrequestView, GetArchivedEvaluationListAPIView, ArchivedEvaluation, ) router = DefaultRouter() @@ -80,4 +80,11 @@ urlpatterns = [ name="evaluation-change-status"), path("archive/quick-evaluation/", ArchiveQuickEvaluationView.as_view(), name="quick-evaluation-archive"), path("archive/evaluation-request/", ArchiveEvaluationrequestView.as_view(), name="evaluation-request-archive"), + + path("archived-evaluvation/", GetArchivedEvaluationListAPIView.as_view(), + name="archived-evaluation"), + + path("auto-evaluvation-change-status/", ArchivedEvaluation.as_view(), + name="archived-evaluation"), + ] diff --git a/core/apps/evaluation/views/auto.py b/core/apps/evaluation/views/auto.py index adc3971..1476ecf 100644 --- a/core/apps/evaluation/views/auto.py +++ b/core/apps/evaluation/views/auto.py @@ -1,13 +1,14 @@ from django.db.models import Q -from django_core.mixins import BaseViewSetMixin from django.shortcuts import get_object_or_404 +from django_core.mixins import BaseViewSetMixin from django_filters.rest_framework import DjangoFilterBackend from drf_spectacular.utils import extend_schema, OpenApiParameter from rest_framework.filters import OrderingFilter, SearchFilter +from rest_framework.generics import GenericAPIView, ListAPIView from rest_framework.permissions import AllowAny, IsAuthenticated -from rest_framework.viewsets import ModelViewSet -from rest_framework.generics import GenericAPIView from rest_framework.response import Response +from rest_framework.views import APIView +from rest_framework.viewsets import ModelViewSet from core.apps.accounts.serializers.user import UserSerializer from core.apps.evaluation.filters.auto import AutoevaluationFilter @@ -154,3 +155,21 @@ class AutoEvaluationListAppraisersView(GenericAPIView): return self.get_paginated_response(serializer.data) except Exception as e: return Response({"error": str(e)}, status=500) + + +@extend_schema(tags=["AutoEvaluation"]) +class GetArchivedEvaluationListAPIView(ListAPIView): + permission_classes = [IsAuthenticated] + def get_queryset(self): + return AutoEvaluationModel.objects.filter(is_archived=True) + + +@extend_schema(tags=["AutoEvaluation"]) +class ArchivedEvaluation(APIView): + permission_classes = [IsAuthenticated] + + def post(self, request, pk): + auto_evaluation = get_object_or_404(AutoEvaluationModel, pk=pk) + auto_evaluation.is_archived = request.data["is_archived"] + auto_evaluation.save() + return Response({"success": True}, status=200)