From b8021c77288517f6eba1219ea4c278b6ed4291cb Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Wed, 22 Apr 2026 14:23:52 +0500 Subject: [PATCH 1/9] add AutoEvaluationRequestView --- .../serializers/auto/AutoEvaluation.py | 19 +++++++++++++------ core/apps/evaluation/urls.py | 5 ++++- core/apps/evaluation/views/auto.py | 17 +++++++++++++++++ 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/core/apps/evaluation/serializers/auto/AutoEvaluation.py b/core/apps/evaluation/serializers/auto/AutoEvaluation.py index e3407de..fcd4d6e 100644 --- a/core/apps/evaluation/serializers/auto/AutoEvaluation.py +++ b/core/apps/evaluation/serializers/auto/AutoEvaluation.py @@ -1,18 +1,19 @@ import re 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 +73,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 +143,6 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer): allow_null=True, ) - class Meta: model = AutoEvaluationModel fields = [ @@ -222,6 +223,7 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer): return attrs + class CreateAutoevaluationSerializer(serializers.ModelSerializer): property_rights = serializers.PrimaryKeyRelatedField( queryset=ReferenceitemModel.objects.all(), @@ -254,7 +256,6 @@ class CreateAutoevaluationSerializer(serializers.ModelSerializer): allow_null=True, ) - class Meta: model = AutoEvaluationModel fields = [ @@ -356,3 +357,9 @@ class AutoEvaluationAppraisersSerializer(serializers.Serializer): raise serializers.ValidationError("Invalid appraisers IDs.") data['users'] = users return data + + +class AutoEvaluationSerializer(ModelSerializer): + class Meta: + model = AutoEvaluationModel + fields = ("brand", "brand_model", "year", "color", "transmission", "condition", "fuel_type", "mileage") diff --git a/core/apps/evaluation/urls.py b/core/apps/evaluation/urls.py index a530b3c..ab62e18 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -29,6 +29,7 @@ from .views import ( DidoxCompanyInfoAPIView, TechPassportAPIView, EvaluationStatusChange, + AutoEvaluationRequestView ) router = DefaultRouter() @@ -53,13 +54,15 @@ router.register("vehicle", VehicleView, basename="vehicle") router.register("valuation", ValuationView, basename="valuation") router.register("property-owner", PropertyOwnerView, basename="property-owner") router.register("customer", CustomerView, basename="customer") +router.register("auto-evaluation-request", AutoEvaluationRequestView, basename="auto") urlpatterns = [ path("", include(router.urls)), path("auto-evaluation/appraisers/", include( [ path("/list/", AutoEvaluationListAppraisersView.as_view(), name="auto-evaluation-list-appraisers"), path("/set/", AutoEvaluationSetAppraisersView.as_view(), name="auto-evaluation-set-appraisers"), - path("/remove/", AutoEvaluationRemoveAppraisersView.as_view(), name="auto-evaluation-remove-appraisers"), + path("/remove/", AutoEvaluationRemoveAppraisersView.as_view(), + name="auto-evaluation-remove-appraisers"), ] )), path( diff --git a/core/apps/evaluation/views/auto.py b/core/apps/evaluation/views/auto.py index adc3971..6e42239 100644 --- a/core/apps/evaluation/views/auto.py +++ b/core/apps/evaluation/views/auto.py @@ -154,3 +154,20 @@ class AutoEvaluationListAppraisersView(GenericAPIView): return self.get_paginated_response(serializer.data) except Exception as e: return Response({"error": str(e)}, status=500) + +class AutoEvaluationRequestView(APIView): + + def post(self, request): + serializer = AutoEvaluationSerializer(data=request.data) + + if serializer.is_valid(): + data = serializer.validated_data + url = "https://uzxarid.felixits.uz/api/v1/ad/price-estimate/" + response = requests.post(url, json=data) + + return Response({ + "success": True, + "external_status": response.status_code, + "data": response.json(), + }) + return Response({"error": serializer.errors}, status=400) From 049cd6ff258cc48c82467ac69e4391f94a1468c4 Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Thu, 23 Apr 2026 13:54:31 +0500 Subject: [PATCH 2/9] /api/v1/admin-user/list/ edit va post --- core/apps/accounts/serializers/user.py | 10 +++++ core/apps/accounts/urls.py | 5 ++- core/apps/accounts/views/user.py | 44 +++++++++++++++++-- .../serializers/auto/AutoEvaluation.py | 15 ++++--- core/apps/evaluation/urls.py | 3 +- core/apps/evaluation/views/auto.py | 18 ++++++-- core/apps/evaluation/views/request.py | 1 + 7 files changed, 82 insertions(+), 14 deletions(-) diff --git a/core/apps/accounts/serializers/user.py b/core/apps/accounts/serializers/user.py index 4f3276e..9ba1eb8 100644 --- a/core/apps/accounts/serializers/user.py +++ b/core/apps/accounts/serializers/user.py @@ -30,3 +30,13 @@ class UserUpdateSerializer(serializers.ModelSerializer): "last_name", "avatar" ] +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 f7a1e2d..fb662b4 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 +from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView, UserListApiView, AdminUserListApiView, \ + UserCreate, UserUpdate from rest_framework.routers import DefaultRouter router = DefaultRouter() @@ -25,4 +26,6 @@ urlpatterns = [ ), path("user/list/", UserListApiView.as_view(), name="user-list"), path("admin-user/list/", AdminUserListApiView.as_view(), name="admin-user-list"), + path("user/create/", UserCreate.as_view(), name="user-create"), + path("user/update/", UserUpdate.as_view(), name="user-update"), ] diff --git a/core/apps/accounts/views/user.py b/core/apps/accounts/views/user.py index f9d4b9e..a9b301e 100644 --- a/core/apps/accounts/views/user.py +++ b/core/apps/accounts/views/user.py @@ -1,15 +1,17 @@ from django.contrib.auth import get_user_model - +from django.shortcuts import get_object_or_404 +from drf_spectacular.utils import extend_schema +from h11 import Response from rest_framework import generics, filters from rest_framework.permissions import IsAuthenticated +from rest_framework.views import APIView -from drf_spectacular.utils import extend_schema - -from core.apps.accounts.serializers.user import UserSerializer from core.apps.accounts.choices.user import RoleChoice +from core.apps.accounts.serializers.user import UserSerializer, UserCreateSerializer User = get_user_model() + @extend_schema(tags=['User']) class UserListApiView(generics.ListAPIView): queryset = User.objects.filter(role=RoleChoice.USER) @@ -29,3 +31,37 @@ class AdminUserListApiView(generics.ListAPIView): permission_classes = [IsAuthenticated] filter_backends = [filters.SearchFilter] search_fields = ['phone', 'first_name', 'last_name'] + + +@extend_schema(tags=['User'], + responses={200: UserSerializer}, + request=UserCreateSerializer) +class UserCreate(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 UserUpdate(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) \ No newline at end of file diff --git a/core/apps/evaluation/serializers/auto/AutoEvaluation.py b/core/apps/evaluation/serializers/auto/AutoEvaluation.py index fcd4d6e..137278f 100644 --- a/core/apps/evaluation/serializers/auto/AutoEvaluation.py +++ b/core/apps/evaluation/serializers/auto/AutoEvaluation.py @@ -1,4 +1,5 @@ import re + from django.contrib.auth import get_user_model from rest_framework import serializers @@ -358,8 +359,12 @@ class AutoEvaluationAppraisersSerializer(serializers.Serializer): data['users'] = users return data - -class AutoEvaluationSerializer(ModelSerializer): - class Meta: - model = AutoEvaluationModel - fields = ("brand", "brand_model", "year", "color", "transmission", "condition", "fuel_type", "mileage") +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 ab62e18..4786343 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -54,7 +54,6 @@ router.register("vehicle", VehicleView, basename="vehicle") router.register("valuation", ValuationView, basename="valuation") router.register("property-owner", PropertyOwnerView, basename="property-owner") router.register("customer", CustomerView, basename="customer") -router.register("auto-evaluation-request", AutoEvaluationRequestView, basename="auto") urlpatterns = [ path("", include(router.urls)), path("auto-evaluation/appraisers/", include( @@ -77,4 +76,6 @@ urlpatterns = [ ), path("evaluation-request//change-status/", EvaluationStatusChange.as_view(), name="evaluation-change-status"), + path("auto-evaluation-request/", AutoEvaluationRequestView.as_view(), + name="evaluation-request-price-estimate"), ] diff --git a/core/apps/evaluation/views/auto.py b/core/apps/evaluation/views/auto.py index 6e42239..1cd8e74 100644 --- a/core/apps/evaluation/views/auto.py +++ b/core/apps/evaluation/views/auto.py @@ -1,17 +1,20 @@ +import requests 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.permissions import AllowAny, IsAuthenticated -from rest_framework.viewsets import ModelViewSet from rest_framework.generics import GenericAPIView +from rest_framework.permissions import AllowAny, IsAuthenticated 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 from core.apps.evaluation.models import AutoEvaluationModel +from core.apps.evaluation.serializers import AutoEvaluationSerializer from core.apps.evaluation.serializers.auto import ( CreateAutoevaluationSerializer, ListAutoevaluationSerializer, @@ -155,7 +158,16 @@ class AutoEvaluationListAppraisersView(GenericAPIView): except Exception as e: return Response({"error": str(e)}, status=500) + + +@extend_schema( + tags=["AutoEvaluation"], + request=AutoEvaluationSerializer, + ) class AutoEvaluationRequestView(APIView): + authentication_classes = [] + permission_classes = [AllowAny] + def post(self, request): serializer = AutoEvaluationSerializer(data=request.data) diff --git a/core/apps/evaluation/views/request.py b/core/apps/evaluation/views/request.py index 1548049..37104f8 100644 --- a/core/apps/evaluation/views/request.py +++ b/core/apps/evaluation/views/request.py @@ -11,6 +11,7 @@ from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import status +from core.apps.accounts.choices import RoleChoice from core.apps.evaluation.filters.request import EvaluationrequestFilter from core.apps.evaluation.models import EvaluationrequestModel from core.apps.evaluation.serializers.request import ( From c4b2a80b2eac86001747d6fd262ee21ffab441b8 Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Thu, 23 Apr 2026 20:03:58 +0500 Subject: [PATCH 3/9] /api/v1/admin-user/list/ edit va post --- core/apps/accounts/urls.py | 6 +++--- core/apps/accounts/views/user.py | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/core/apps/accounts/urls.py b/core/apps/accounts/urls.py index fb662b4..c9e5ca9 100644 --- a/core/apps/accounts/urls.py +++ b/core/apps/accounts/urls.py @@ -5,7 +5,7 @@ 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, \ - UserCreate, UserUpdate + AdminUpdate, AdminCreate from rest_framework.routers import DefaultRouter router = DefaultRouter() @@ -26,6 +26,6 @@ urlpatterns = [ ), path("user/list/", UserListApiView.as_view(), name="user-list"), path("admin-user/list/", AdminUserListApiView.as_view(), name="admin-user-list"), - path("user/create/", UserCreate.as_view(), name="user-create"), - path("user/update/", UserUpdate.as_view(), name="user-update"), + path("user/create/", AdminCreate.as_view(), name="user-create"), + path("user/update/", AdminUpdate.as_view(), name="user-update"), ] diff --git a/core/apps/accounts/views/user.py b/core/apps/accounts/views/user.py index a9b301e..70f0585 100644 --- a/core/apps/accounts/views/user.py +++ b/core/apps/accounts/views/user.py @@ -36,7 +36,7 @@ class AdminUserListApiView(generics.ListAPIView): @extend_schema(tags=['User'], responses={200: UserSerializer}, request=UserCreateSerializer) -class UserCreate(APIView): +class AdminCreate(APIView): permission_classes = [IsAuthenticated] def post(self, request): @@ -52,7 +52,7 @@ class UserCreate(APIView): @extend_schema(tags=['User'], responses={200: UserSerializer}, request=UserCreateSerializer) -class UserUpdate(APIView): +class AdminUpdate(APIView): permission_classes = [IsAuthenticated] def put(self, request, pk): @@ -64,4 +64,6 @@ class UserUpdate(APIView): serializer.is_valid(raise_exception=True) serializer.save() - return Response(serializer.data, status=200) \ No newline at end of file + return Response(serializer.data, status=200) + + From d2f8d73cdd1ac5d0d2af3883308f28e501699af9 Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Thu, 23 Apr 2026 20:05:16 +0500 Subject: [PATCH 4/9] /api/v1/admin-user/list/ edit va post --- core/apps/accounts/urls.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/apps/accounts/urls.py b/core/apps/accounts/urls.py index c9e5ca9..ffd0226 100644 --- a/core/apps/accounts/urls.py +++ b/core/apps/accounts/urls.py @@ -26,6 +26,6 @@ urlpatterns = [ ), path("user/list/", UserListApiView.as_view(), name="user-list"), path("admin-user/list/", AdminUserListApiView.as_view(), name="admin-user-list"), - path("user/create/", AdminCreate.as_view(), name="user-create"), - path("user/update/", AdminUpdate.as_view(), name="user-update"), + path("admin/create/", AdminCreate.as_view(), name="user-create"), + path("admin/update/", AdminUpdate.as_view(), name="user-update"), ] From af559daddac69336d1b0563c3236e53180fad26d Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Fri, 24 Apr 2026 11:04:37 +0500 Subject: [PATCH 5/9] ADD permission --- core/apps/accounts/models/user.py | 2 ++ .../apps/evaluation/permissions/permission.py | 21 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 core/apps/evaluation/permissions/permission.py diff --git a/core/apps/accounts/models/user.py b/core/apps/accounts/models/user.py index d6e375f..154fb35 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) + role_permission = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True) USERNAME_FIELD = "phone" objects = UserManager() diff --git a/core/apps/evaluation/permissions/permission.py b/core/apps/evaluation/permissions/permission.py new file mode 100644 index 0000000..3905419 --- /dev/null +++ b/core/apps/evaluation/permissions/permission.py @@ -0,0 +1,21 @@ +from django.db import models + + +class Role(models.Model): + name = models.CharField(max_length=50) + + +class Permission(models.Model): + class Action(models.TextChoices): + CREATE = "create_avto_valuation" + CREATE_FAST = "create_fast_auto_valuation" + CREATE_AVTO_APPEAL = "create_avto_appeal" + + page = models.CharField(max_length=100) + section = models.CharField(max_length=100, null=True, blank=True) + action = models.CharField(max_length=20, choices=Action.choices) + + +class RolePermission(models.Model): + role = models.ForeignKey(Role, on_delete=models.CASCADE) + permission = models.ForeignKey(Permission, on_delete=models.CASCADE) From 82489cf64cb9b3e7fae48d3ac41cbed72cb0e310 Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Fri, 24 Apr 2026 11:22:58 +0500 Subject: [PATCH 6/9] ADD archivedet evaluvation --- core/apps/evaluation/models/auto.py | 6 ++++++ core/apps/evaluation/urls.py | 4 +++- core/apps/evaluation/views/auto.py | 22 ++++++++++++++++------ 3 files changed, 25 insertions(+), 7 deletions(-) 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/urls.py b/core/apps/evaluation/urls.py index 4786343..a189f7e 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -29,7 +29,7 @@ from .views import ( DidoxCompanyInfoAPIView, TechPassportAPIView, EvaluationStatusChange, - AutoEvaluationRequestView + AutoEvaluationRequestView, GetArchivedEvaluation, GetEvaluation ) router = DefaultRouter() @@ -78,4 +78,6 @@ urlpatterns = [ name="evaluation-change-status"), path("auto-evaluation-request/", AutoEvaluationRequestView.as_view(), name="evaluation-request-price-estimate"), + path("archived-evaluvation/", GetArchivedEvaluation.as_view(), + name="archived-evaluation"), ] diff --git a/core/apps/evaluation/views/auto.py b/core/apps/evaluation/views/auto.py index 1cd8e74..f0ded50 100644 --- a/core/apps/evaluation/views/auto.py +++ b/core/apps/evaluation/views/auto.py @@ -5,7 +5,7 @@ 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 +from rest_framework.generics import GenericAPIView, ListAPIView from rest_framework.permissions import AllowAny, IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView @@ -159,16 +159,14 @@ class AutoEvaluationListAppraisersView(GenericAPIView): return Response({"error": str(e)}, status=500) - @extend_schema( - tags=["AutoEvaluation"], - request=AutoEvaluationSerializer, - ) + tags=["AutoEvaluation"], + request=AutoEvaluationSerializer, +) class AutoEvaluationRequestView(APIView): authentication_classes = [] permission_classes = [AllowAny] - def post(self, request): serializer = AutoEvaluationSerializer(data=request.data) @@ -183,3 +181,15 @@ class AutoEvaluationRequestView(APIView): "data": response.json(), }) return Response({"error": serializer.errors}, status=400) + + +@extend_schema(tags=["AutoEvaluation"]) +class GetArchivedEvaluation(ListAPIView): + authentication_classes = [] + permission_classes = [IsAuthenticated] + + def get_queryset(self): + return AutoEvaluationModel.objects.filter(is_archived=True) + + + From e27a9b7f118e2fdb78801100b2bddba02f3887d3 Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Fri, 24 Apr 2026 11:28:29 +0500 Subject: [PATCH 7/9] UPDATE --- core/apps/evaluation/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/apps/evaluation/urls.py b/core/apps/evaluation/urls.py index a189f7e..45371ec 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -29,7 +29,7 @@ from .views import ( DidoxCompanyInfoAPIView, TechPassportAPIView, EvaluationStatusChange, - AutoEvaluationRequestView, GetArchivedEvaluation, GetEvaluation + AutoEvaluationRequestView, GetArchivedEvaluation ) router = DefaultRouter() From deebae384ce309ed4b3fad7dcef2cd635946bcdb Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Fri, 24 Apr 2026 16:00:17 +0500 Subject: [PATCH 8/9] UPDATE --- core/apps/accounts/models/user.py | 2 +- core/apps/accounts/urls.py | 6 +- core/apps/accounts/views/user.py | 6 +- .../apps/evaluation/permissions/permission.py | 67 +++++++++++++++---- core/apps/evaluation/urls.py | 6 +- core/apps/evaluation/views/auto.py | 37 +++------- core/apps/evaluation/views/request.py | 10 ++- 7 files changed, 76 insertions(+), 58 deletions(-) diff --git a/core/apps/accounts/models/user.py b/core/apps/accounts/models/user.py index 154fb35..f24edda 100644 --- a/core/apps/accounts/models/user.py +++ b/core/apps/accounts/models/user.py @@ -18,7 +18,7 @@ class User(auth_models.AbstractUser): default=RoleChoice.USER, ) avatar = models.ImageField(upload_to="avatars/", null=True, blank=True) - role_permission = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True) + permission = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True) USERNAME_FIELD = "phone" objects = UserManager() diff --git a/core/apps/accounts/urls.py b/core/apps/accounts/urls.py index ffd0226..507a041 100644 --- a/core/apps/accounts/urls.py +++ b/core/apps/accounts/urls.py @@ -5,7 +5,7 @@ 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, \ - AdminUpdate, AdminCreate + AdminUpdateAPIView, AdminCreateAPIView from rest_framework.routers import DefaultRouter router = DefaultRouter() @@ -26,6 +26,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/", AdminCreate.as_view(), name="user-create"), - path("admin/update/", AdminUpdate.as_view(), name="user-update"), + 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 70f0585..fce33f6 100644 --- a/core/apps/accounts/views/user.py +++ b/core/apps/accounts/views/user.py @@ -1,9 +1,9 @@ from django.contrib.auth import get_user_model from django.shortcuts import get_object_or_404 from drf_spectacular.utils import extend_schema -from h11 import Response from rest_framework import generics, filters from rest_framework.permissions import IsAuthenticated +from rest_framework.response import Response from rest_framework.views import APIView from core.apps.accounts.choices.user import RoleChoice @@ -36,7 +36,7 @@ class AdminUserListApiView(generics.ListAPIView): @extend_schema(tags=['User'], responses={200: UserSerializer}, request=UserCreateSerializer) -class AdminCreate(APIView): +class AdminCreateAPIView(APIView): permission_classes = [IsAuthenticated] def post(self, request): @@ -52,7 +52,7 @@ class AdminCreate(APIView): @extend_schema(tags=['User'], responses={200: UserSerializer}, request=UserCreateSerializer) -class AdminUpdate(APIView): +class AdminUpdateAPIView(APIView): permission_classes = [IsAuthenticated] def put(self, request, pk): diff --git a/core/apps/evaluation/permissions/permission.py b/core/apps/evaluation/permissions/permission.py index 3905419..3b305c2 100644 --- a/core/apps/evaluation/permissions/permission.py +++ b/core/apps/evaluation/permissions/permission.py @@ -1,21 +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=50) + 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 Permission(models.Model): - class Action(models.TextChoices): - CREATE = "create_avto_valuation" - CREATE_FAST = "create_fast_auto_valuation" - CREATE_AVTO_APPEAL = "create_avto_appeal" + class Meta: + verbose_name = _('Rol') + verbose_name_plural = _('Rollar') - page = models.CharField(max_length=100) - section = models.CharField(max_length=100, null=True, blank=True) - action = models.CharField(max_length=20, choices=Action.choices) - - -class RolePermission(models.Model): - role = models.ForeignKey(Role, on_delete=models.CASCADE) - permission = models.ForeignKey(Permission, on_delete=models.CASCADE) diff --git a/core/apps/evaluation/urls.py b/core/apps/evaluation/urls.py index 45371ec..d1cde28 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -29,7 +29,7 @@ from .views import ( DidoxCompanyInfoAPIView, TechPassportAPIView, EvaluationStatusChange, - AutoEvaluationRequestView, GetArchivedEvaluation + GetArchivedEvaluationListAPIView ) router = DefaultRouter() @@ -76,8 +76,6 @@ urlpatterns = [ ), path("evaluation-request//change-status/", EvaluationStatusChange.as_view(), name="evaluation-change-status"), - path("auto-evaluation-request/", AutoEvaluationRequestView.as_view(), - name="evaluation-request-price-estimate"), - path("archived-evaluvation/", GetArchivedEvaluation.as_view(), + path("archived-evaluvation/", GetArchivedEvaluationListAPIView.as_view(), name="archived-evaluation"), ] diff --git a/core/apps/evaluation/views/auto.py b/core/apps/evaluation/views/auto.py index f0ded50..cfc59de 100644 --- a/core/apps/evaluation/views/auto.py +++ b/core/apps/evaluation/views/auto.py @@ -1,4 +1,3 @@ -import requests from django.db.models import Q from django.shortcuts import get_object_or_404 from django_core.mixins import BaseViewSetMixin @@ -14,7 +13,6 @@ from rest_framework.viewsets import ModelViewSet from core.apps.accounts.serializers.user import UserSerializer from core.apps.evaluation.filters.auto import AutoevaluationFilter from core.apps.evaluation.models import AutoEvaluationModel -from core.apps.evaluation.serializers import AutoEvaluationSerializer from core.apps.evaluation.serializers.auto import ( CreateAutoevaluationSerializer, ListAutoevaluationSerializer, @@ -159,32 +157,8 @@ class AutoEvaluationListAppraisersView(GenericAPIView): return Response({"error": str(e)}, status=500) -@extend_schema( - tags=["AutoEvaluation"], - request=AutoEvaluationSerializer, -) -class AutoEvaluationRequestView(APIView): - authentication_classes = [] - permission_classes = [AllowAny] - - def post(self, request): - serializer = AutoEvaluationSerializer(data=request.data) - - if serializer.is_valid(): - data = serializer.validated_data - url = "https://uzxarid.felixits.uz/api/v1/ad/price-estimate/" - response = requests.post(url, json=data) - - return Response({ - "success": True, - "external_status": response.status_code, - "data": response.json(), - }) - return Response({"error": serializer.errors}, status=400) - - @extend_schema(tags=["AutoEvaluation"]) -class GetArchivedEvaluation(ListAPIView): +class GetArchivedEvaluationListAPIView(ListAPIView): authentication_classes = [] permission_classes = [IsAuthenticated] @@ -192,4 +166,13 @@ class GetArchivedEvaluation(ListAPIView): return AutoEvaluationModel.objects.filter(is_archived=True) +@extend_schema(tags=["AutoEvaluation"]) +class ArchivedEvaluation(APIView): + authentication_classes = [] + 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) diff --git a/core/apps/evaluation/views/request.py b/core/apps/evaluation/views/request.py index 37104f8..ab17196 100644 --- a/core/apps/evaluation/views/request.py +++ b/core/apps/evaluation/views/request.py @@ -1,17 +1,16 @@ 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 +from rest_framework import status from rest_framework.filters import OrderingFilter, SearchFilter -from rest_framework.pagination import PageNumberPagination -from rest_framework.permissions import AllowAny, IsAuthenticated -from rest_framework.viewsets import ModelViewSet +from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView -from rest_framework import status +from rest_framework.viewsets import ModelViewSet from core.apps.accounts.choices import RoleChoice +from core.apps.evaluation.choices.request import RequestStatus from core.apps.evaluation.filters.request import EvaluationrequestFilter from core.apps.evaluation.models import EvaluationrequestModel from core.apps.evaluation.serializers.request import ( @@ -19,7 +18,6 @@ from core.apps.evaluation.serializers.request import ( ListEvaluationrequestSerializer, RetrieveEvaluationrequestSerializer, ) -from core.apps.evaluation.choices.request import RequestStatus # class RequestPagination(PageNumberPagination): From 84cc11fe2a9be83b65ced5ae393e825172ddca98 Mon Sep 17 00:00:00 2001 From: Shaxobff Date: Fri, 24 Apr 2026 16:21:19 +0500 Subject: [PATCH 9/9] UPDATE --- core/apps/accounts/views/user.py | 1 + core/apps/evaluation/urls.py | 4 ++++ core/apps/evaluation/views/auto.py | 2 -- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/apps/accounts/views/user.py b/core/apps/accounts/views/user.py index fce33f6..89619d9 100644 --- a/core/apps/accounts/views/user.py +++ b/core/apps/accounts/views/user.py @@ -52,6 +52,7 @@ class AdminCreateAPIView(APIView): @extend_schema(tags=['User'], responses={200: UserSerializer}, request=UserCreateSerializer) + class AdminUpdateAPIView(APIView): permission_classes = [IsAuthenticated] diff --git a/core/apps/evaluation/urls.py b/core/apps/evaluation/urls.py index d1cde28..25bd122 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -76,6 +76,10 @@ urlpatterns = [ ), path("evaluation-request//change-status/", EvaluationStatusChange.as_view(), name="evaluation-change-status"), + path("archived-evaluvation/", GetArchivedEvaluationListAPIView.as_view(), name="archived-evaluation"), + + path("auto-evaluvation-change-status/", GetArchivedEvaluationListAPIView.as_view(), + name="archived-evaluation"), ] diff --git a/core/apps/evaluation/views/auto.py b/core/apps/evaluation/views/auto.py index cfc59de..d1dfd4e 100644 --- a/core/apps/evaluation/views/auto.py +++ b/core/apps/evaluation/views/auto.py @@ -159,7 +159,6 @@ class AutoEvaluationListAppraisersView(GenericAPIView): @extend_schema(tags=["AutoEvaluation"]) class GetArchivedEvaluationListAPIView(ListAPIView): - authentication_classes = [] permission_classes = [IsAuthenticated] def get_queryset(self): @@ -168,7 +167,6 @@ class GetArchivedEvaluationListAPIView(ListAPIView): @extend_schema(tags=["AutoEvaluation"]) class ArchivedEvaluation(APIView): - authentication_classes = [] permission_classes = [IsAuthenticated] def post(self, request, pk):