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/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..ffd0226 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, \ + AdminUpdate, AdminCreate 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("admin/create/", AdminCreate.as_view(), name="user-create"), + path("admin/update/", AdminUpdate.as_view(), name="user-update"), ] diff --git a/core/apps/accounts/views/user.py b/core/apps/accounts/views/user.py index f9d4b9e..70f0585 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,39 @@ 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 AdminCreate(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 AdminUpdate(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..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) 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 a530b3c..45371ec 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -29,6 +29,7 @@ from .views import ( DidoxCompanyInfoAPIView, TechPassportAPIView, EvaluationStatusChange, + AutoEvaluationRequestView, GetArchivedEvaluation ) router = DefaultRouter() @@ -59,7 +60,8 @@ urlpatterns = [ [ 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( @@ -74,4 +76,8 @@ 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(), + name="archived-evaluation"), ] diff --git a/core/apps/evaluation/views/auto.py b/core/apps/evaluation/views/auto.py index adc3971..f0ded50 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.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 from core.apps.evaluation.models import AutoEvaluationModel +from core.apps.evaluation.serializers import AutoEvaluationSerializer from core.apps.evaluation.serializers.auto import ( CreateAutoevaluationSerializer, ListAutoevaluationSerializer, @@ -154,3 +157,39 @@ 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"], + 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): + authentication_classes = [] + permission_classes = [IsAuthenticated] + + def get_queryset(self): + return AutoEvaluationModel.objects.filter(is_archived=True) + + + 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 (