Compare commits
7 Commits
user-crud
...
e27a9b7f11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e27a9b7f11 | ||
|
|
82489cf64c | ||
|
|
af559dadda | ||
|
|
d2f8d73cdd | ||
|
|
c4b2a80b2e | ||
|
|
049cd6ff25 | ||
|
|
b8021c7728 |
4
.github/workflows/deploy.yaml
vendored
4
.github/workflows/deploy.yaml
vendored
@@ -153,7 +153,7 @@ jobs:
|
|||||||
update_env \
|
update_env \
|
||||||
"DB_HOST=postgres" \
|
"DB_HOST=postgres" \
|
||||||
"DB_NAME=sifatbahodb" \
|
"DB_NAME=sifatbahodb" \
|
||||||
"DB_PORT=5432" \
|
"DB_PORT=5432"
|
||||||
"DIDOX_TOKEN=${{ secrets.DIDOX_TOKEN }}"
|
|
||||||
export PORT=8085
|
export PORT=8085
|
||||||
docker stack deploy -c stack.yaml ${{ env.PROJECT_NAME }} --with-registry-auth
|
docker stack deploy -c stack.yaml ${{ env.PROJECT_NAME }} --with-registry-auth
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from config.env import env
|
|||||||
|
|
||||||
|
|
||||||
def home(request):
|
def home(request):
|
||||||
return HttpResponse("OK: #1a985ffa4b785b63a71b9e0cdd78042c3fcda239")
|
return HttpResponse("OK: #46c96214578b78c1fe731f9a2ceb4429b81d4da9")
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from django.db import models
|
|||||||
|
|
||||||
from ..choices import RoleChoice
|
from ..choices import RoleChoice
|
||||||
from ..managers import UserManager
|
from ..managers import UserManager
|
||||||
|
from ...evaluation.permissions.permission import Role
|
||||||
|
|
||||||
|
|
||||||
class User(auth_models.AbstractUser):
|
class User(auth_models.AbstractUser):
|
||||||
@@ -17,6 +18,7 @@ class User(auth_models.AbstractUser):
|
|||||||
default=RoleChoice.USER,
|
default=RoleChoice.USER,
|
||||||
)
|
)
|
||||||
avatar = models.ImageField(upload_to="avatars/", null=True, blank=True)
|
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"
|
USERNAME_FIELD = "phone"
|
||||||
objects = UserManager()
|
objects = UserManager()
|
||||||
|
|||||||
@@ -30,16 +30,13 @@ class UserUpdateSerializer(serializers.ModelSerializer):
|
|||||||
"last_name",
|
"last_name",
|
||||||
"avatar"
|
"avatar"
|
||||||
]
|
]
|
||||||
|
class UserCreateSerializer(serializers.ModelSerializer):
|
||||||
class AdminUserSerializer(serializers.ModelSerializer):
|
|
||||||
avatar = serializers.SerializerMethodField(method_name='get_avatar')
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = get_user_model()
|
model = get_user_model()
|
||||||
fields = "__all__"
|
fields = [
|
||||||
|
"phone",
|
||||||
def get_avatar(self, obj):
|
"first_name",
|
||||||
request = self.context.get('request')
|
"last_name",
|
||||||
if obj.avatar:
|
"password",
|
||||||
return request.build_absolute_uri(obj.avatar.url)
|
"role"
|
||||||
return None
|
]
|
||||||
@@ -4,7 +4,8 @@ Accounts app urls
|
|||||||
|
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework_simplejwt import views as jwt_views
|
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, \
|
||||||
|
AdminUpdate, AdminCreate
|
||||||
from rest_framework.routers import DefaultRouter
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
@@ -12,7 +13,6 @@ router.register("auth", RegisterView, basename="auth")
|
|||||||
router.register("auth", ResetPasswordView, basename="reset-password")
|
router.register("auth", ResetPasswordView, basename="reset-password")
|
||||||
router.register("auth", MeView, basename="me")
|
router.register("auth", MeView, basename="me")
|
||||||
router.register("auth", ChangePasswordView, basename="change-password")
|
router.register("auth", ChangePasswordView, basename="change-password")
|
||||||
router.register("user", AdminUserView, basename="user-crud")
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
@@ -26,4 +26,6 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
path("user/list/", UserListApiView.as_view(), name="user-list"),
|
path("user/list/", UserListApiView.as_view(), name="user-list"),
|
||||||
path("admin-user/list/", AdminUserListApiView.as_view(), name="admin-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"),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,18 +1,17 @@
|
|||||||
from django.contrib.auth import get_user_model
|
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 import generics, filters
|
||||||
from rest_framework.permissions import IsAuthenticated
|
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, AdminUserSerializer
|
|
||||||
from core.apps.accounts.choices.user import RoleChoice
|
from core.apps.accounts.choices.user import RoleChoice
|
||||||
from django_core.mixins import BaseViewSetMixin
|
from core.apps.accounts.serializers.user import UserSerializer, UserCreateSerializer
|
||||||
from rest_framework.viewsets import ModelViewSet
|
|
||||||
|
|
||||||
|
|
||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
@extend_schema(tags=['User'])
|
@extend_schema(tags=['User'])
|
||||||
class UserListApiView(generics.ListAPIView):
|
class UserListApiView(generics.ListAPIView):
|
||||||
queryset = User.objects.filter(role=RoleChoice.USER)
|
queryset = User.objects.filter(role=RoleChoice.USER)
|
||||||
@@ -34,14 +33,37 @@ class AdminUserListApiView(generics.ListAPIView):
|
|||||||
search_fields = ['phone', 'first_name', 'last_name']
|
search_fields = ['phone', 'first_name', 'last_name']
|
||||||
|
|
||||||
|
|
||||||
@extend_schema(tags=["User"],request=AdminUserSerializer)
|
@extend_schema(tags=['User'],
|
||||||
class AdminUserView(BaseViewSetMixin, ModelViewSet):
|
responses={200: UserSerializer},
|
||||||
queryset = User.objects.filter(role=RoleChoice.USER)
|
request=UserCreateSerializer)
|
||||||
serializer_class = AdminUserSerializer
|
class AdminCreate(APIView):
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
filter_backends = [filters.SearchFilter]
|
|
||||||
search_fields = ['phone', 'first_name', 'last_name']
|
|
||||||
|
|
||||||
def serializer_context(self):
|
def post(self, request):
|
||||||
return self.serializer_class(context={"request": 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)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
# Generated by Django 6.0.4 on 2026-04-23 11:07
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evaluation', '0031_remove_autoevaluationmodel_object_location_city_and_more'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='CertificateModel',
|
|
||||||
fields=[
|
|
||||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
|
||||||
('updated_at', models.DateTimeField(auto_now=True)),
|
|
||||||
('title', models.CharField(max_length=255, verbose_name='title')),
|
|
||||||
('file_url', models.URLField(max_length=255, verbose_name='file url')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'Certificate',
|
|
||||||
'verbose_name_plural': 'Certificates',
|
|
||||||
'db_table': 'certificate',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 6.0.4 on 2026-04-23 07:22
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evaluation', '0031_remove_autoevaluationmodel_object_location_city_and_more'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='evaluationrequestmodel',
|
|
||||||
name='is_archive',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='is archive'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 6.0.4 on 2026-04-23 07:24
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evaluation', '0031_remove_autoevaluationmodel_object_location_city_and_more'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='quickevaluationmodel',
|
|
||||||
name='is_archive',
|
|
||||||
field=models.BooleanField(default=False, verbose_name='is archive'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Generated by Django 6.0.4 on 2026-04-23 11:22
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evaluation', '0032_certificatemodel'),
|
|
||||||
('evaluation', '0032_evaluationrequestmodel_is_archive'),
|
|
||||||
('evaluation', '0032_quickevaluationmodel_is_archive'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
]
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# Generated by Django 6.0.4 on 2026-04-23 13:42
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('evaluation', '0033_merge_20260423_1622'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.RemoveField(
|
|
||||||
model_name='certificatemodel',
|
|
||||||
name='file_url',
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='certificatemodel',
|
|
||||||
name='file',
|
|
||||||
field=models.FileField(blank=True, null=True, upload_to='certificates/', verbose_name='file'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -11,4 +11,3 @@ from .report import * # noqa
|
|||||||
from .request import * # noqa
|
from .request import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
from .certificate import * # noqa
|
|
||||||
|
|||||||
@@ -267,6 +267,12 @@ class AutoEvaluationModel(AbstractBaseModel):
|
|||||||
choices=AutoEvaluationStatus.choices,
|
choices=AutoEvaluationStatus.choices,
|
||||||
default=AutoEvaluationStatus.CREATED,
|
default=AutoEvaluationStatus.CREATED,
|
||||||
)
|
)
|
||||||
|
is_archived = models.BooleanField(
|
||||||
|
verbose_name=_("is archived"),
|
||||||
|
default=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Auto Evaluation {self.registration_number or self.pk}"
|
return f"Auto Evaluation {self.registration_number or self.pk}"
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
from django_core.models import AbstractBaseModel
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from model_bakery import baker
|
|
||||||
|
|
||||||
|
|
||||||
class CertificateModel(AbstractBaseModel):
|
|
||||||
title = models.CharField(
|
|
||||||
verbose_name=_("title"),
|
|
||||||
max_length=255
|
|
||||||
)
|
|
||||||
|
|
||||||
file = models.FileField(
|
|
||||||
verbose_name=_("file"),
|
|
||||||
upload_to="certificates/",
|
|
||||||
blank=True,
|
|
||||||
null=True
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.title
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _baker(cls):
|
|
||||||
return baker.make(cls)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
db_table = "certificate"
|
|
||||||
verbose_name = _("Certificate")
|
|
||||||
verbose_name_plural = _("Certificates")
|
|
||||||
@@ -132,11 +132,6 @@ class QuickEvaluationModel(AbstractBaseModel):
|
|||||||
default=QuickEvaluationStatus.CREATED,
|
default=QuickEvaluationStatus.CREATED,
|
||||||
)
|
)
|
||||||
|
|
||||||
is_archive = models.BooleanField(
|
|
||||||
verbose_name=_("is archive"),
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Quick Evaluation {self.pk} by {self.created_by}"
|
return f"Quick Evaluation {self.pk} by {self.created_by}"
|
||||||
|
|
||||||
|
|||||||
@@ -118,10 +118,6 @@ class EvaluationrequestModel(AbstractBaseModel):
|
|||||||
choices=RequestStatus.choices,
|
choices=RequestStatus.choices,
|
||||||
default=RequestStatus.PENDING,
|
default=RequestStatus.PENDING,
|
||||||
)
|
)
|
||||||
is_archive = models.BooleanField(
|
|
||||||
verbose_name=_("is archive"),
|
|
||||||
default=False,
|
|
||||||
)
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Requests #{self.pk} — {self.get_rate_type_display()}"
|
return f"Requests #{self.pk} — {self.get_rate_type_display()}"
|
||||||
|
|
||||||
|
|||||||
21
core/apps/evaluation/permissions/permission.py
Normal file
21
core/apps/evaluation/permissions/permission.py
Normal file
@@ -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)
|
||||||
@@ -12,4 +12,3 @@ from .request import * # noqa
|
|||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
from .tech_passport import * # noqa
|
from .tech_passport import * # noqa
|
||||||
from .certificate import * # noqa
|
|
||||||
|
|||||||
@@ -1,18 +1,20 @@
|
|||||||
import re
|
import re
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
|
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
from rest_framework import serializers
|
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.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()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
class BaseAutoevaluationSerializer(serializers.ModelSerializer):
|
class BaseAutoevaluationSerializer(serializers.ModelSerializer):
|
||||||
status_display = serializers.CharField(source="get_status_display", read_only=True)
|
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_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)
|
rate_type = ListReferenceitemSerializer(read_only=True)
|
||||||
value_determined = ListReferenceitemSerializer(read_only=True)
|
value_determined = ListReferenceitemSerializer(read_only=True)
|
||||||
property_rights = ListReferenceitemSerializer(read_only=True)
|
property_rights = ListReferenceitemSerializer(read_only=True)
|
||||||
@@ -72,6 +74,7 @@ class ListAutoevaluationSerializer(BaseAutoevaluationSerializer):
|
|||||||
class RetrieveAutoevaluationSerializer(BaseAutoevaluationSerializer):
|
class RetrieveAutoevaluationSerializer(BaseAutoevaluationSerializer):
|
||||||
car_type_display = serializers.CharField(source="get_car_type_display", read_only=True, default=None)
|
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)
|
car_wheel_display = serializers.CharField(source="get_car_wheel_display", read_only=True, default=None)
|
||||||
|
|
||||||
# object_location_highways_display = serializers.CharField(
|
# object_location_highways_display = serializers.CharField(
|
||||||
# source="get_object_location_highways_display", read_only=True, default=None
|
# source="get_object_location_highways_display", read_only=True, default=None
|
||||||
# )
|
# )
|
||||||
@@ -141,7 +144,6 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
allow_null=True,
|
allow_null=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = AutoEvaluationModel
|
model = AutoEvaluationModel
|
||||||
fields = [
|
fields = [
|
||||||
@@ -222,6 +224,7 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
|
||||||
class CreateAutoevaluationSerializer(serializers.ModelSerializer):
|
class CreateAutoevaluationSerializer(serializers.ModelSerializer):
|
||||||
property_rights = serializers.PrimaryKeyRelatedField(
|
property_rights = serializers.PrimaryKeyRelatedField(
|
||||||
queryset=ReferenceitemModel.objects.all(),
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
@@ -254,7 +257,6 @@ class CreateAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
allow_null=True,
|
allow_null=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = AutoEvaluationModel
|
model = AutoEvaluationModel
|
||||||
fields = [
|
fields = [
|
||||||
@@ -356,3 +358,13 @@ class AutoEvaluationAppraisersSerializer(serializers.Serializer):
|
|||||||
raise serializers.ValidationError("Invalid appraisers IDs.")
|
raise serializers.ValidationError("Invalid appraisers IDs.")
|
||||||
data['users'] = users
|
data['users'] = users
|
||||||
return data
|
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()
|
||||||
@@ -1 +0,0 @@
|
|||||||
from .certificate import * # noqa
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
from rest_framework import serializers
|
|
||||||
from core.apps.evaluation.models import CertificateModel
|
|
||||||
|
|
||||||
|
|
||||||
class BaseCertificateSerializer(serializers.ModelSerializer):
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = CertificateModel
|
|
||||||
fields = [
|
|
||||||
"id",
|
|
||||||
"title",
|
|
||||||
"file",
|
|
||||||
]
|
|
||||||
@@ -38,8 +38,7 @@ class BaseQuickevaluationSerializer(serializers.ModelSerializer):
|
|||||||
"state_car_name",
|
"state_car_name",
|
||||||
"created_at",
|
"created_at",
|
||||||
"distance_covered",
|
"distance_covered",
|
||||||
"tex_passport_serie_num",
|
"tex_passport_serie_num"
|
||||||
"is_archive"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -126,8 +125,3 @@ class CreateQuickevaluationSerializer(serializers.ModelSerializer):
|
|||||||
if request and request.user and request.user.is_authenticated:
|
if request and request.user and request.user.is_authenticated:
|
||||||
validated_data["created_by"] = request.user
|
validated_data["created_by"] = request.user
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
|
|
||||||
|
|
||||||
class ArchiveQuickevaluationSerializer(serializers.Serializer):
|
|
||||||
id = serializers.IntegerField(required=True)
|
|
||||||
is_archive = serializers.BooleanField(required=True)
|
|
||||||
@@ -55,7 +55,6 @@ class BaseEvaluationrequestSerializer(serializers.ModelSerializer):
|
|||||||
"user",
|
"user",
|
||||||
"created_at",
|
"created_at",
|
||||||
"updated_at",
|
"updated_at",
|
||||||
"is_archive",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_location(self, obj):
|
def get_location(self, obj):
|
||||||
@@ -184,7 +183,3 @@ class CreateEvaluationrequestSerializer(serializers.ModelSerializer):
|
|||||||
validated_data["location_name"] = str(location_name)
|
validated_data["location_name"] = str(location_name)
|
||||||
validated_data["user"] = self.context["request"].user
|
validated_data["user"] = self.context["request"].user
|
||||||
return super().create(validated_data)
|
return super().create(validated_data)
|
||||||
|
|
||||||
class ArchiveEvaluationrequestSerializer(serializers.Serializer):
|
|
||||||
id = serializers.IntegerField(required=True)
|
|
||||||
is_archive = serializers.BooleanField(required=True)
|
|
||||||
@@ -29,9 +29,7 @@ from .views import (
|
|||||||
DidoxCompanyInfoAPIView,
|
DidoxCompanyInfoAPIView,
|
||||||
TechPassportAPIView,
|
TechPassportAPIView,
|
||||||
EvaluationStatusChange,
|
EvaluationStatusChange,
|
||||||
CertificateView,
|
AutoEvaluationRequestView, GetArchivedEvaluation
|
||||||
ArchiveQuickEvaluationView,
|
|
||||||
ArchiveEvaluationrequestView,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
@@ -56,14 +54,14 @@ router.register("vehicle", VehicleView, basename="vehicle")
|
|||||||
router.register("valuation", ValuationView, basename="valuation")
|
router.register("valuation", ValuationView, basename="valuation")
|
||||||
router.register("property-owner", PropertyOwnerView, basename="property-owner")
|
router.register("property-owner", PropertyOwnerView, basename="property-owner")
|
||||||
router.register("customer", CustomerView, basename="customer")
|
router.register("customer", CustomerView, basename="customer")
|
||||||
router.register("certificate", CertificateView, basename="certificate")
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", include(router.urls)),
|
path("", include(router.urls)),
|
||||||
path("auto-evaluation/appraisers/", include(
|
path("auto-evaluation/appraisers/", include(
|
||||||
[
|
[
|
||||||
path("<int:id>/list/", AutoEvaluationListAppraisersView.as_view(), name="auto-evaluation-list-appraisers"),
|
path("<int:id>/list/", AutoEvaluationListAppraisersView.as_view(), name="auto-evaluation-list-appraisers"),
|
||||||
path("<int:id>/set/", AutoEvaluationSetAppraisersView.as_view(), name="auto-evaluation-set-appraisers"),
|
path("<int:id>/set/", AutoEvaluationSetAppraisersView.as_view(), name="auto-evaluation-set-appraisers"),
|
||||||
path("<int:id>/remove/", AutoEvaluationRemoveAppraisersView.as_view(), name="auto-evaluation-remove-appraisers"),
|
path("<int:id>/remove/", AutoEvaluationRemoveAppraisersView.as_view(),
|
||||||
|
name="auto-evaluation-remove-appraisers"),
|
||||||
]
|
]
|
||||||
)),
|
)),
|
||||||
path(
|
path(
|
||||||
@@ -78,6 +76,8 @@ urlpatterns = [
|
|||||||
),
|
),
|
||||||
path("evaluation-request/<int:pk>/change-status/", EvaluationStatusChange.as_view(),
|
path("evaluation-request/<int:pk>/change-status/", EvaluationStatusChange.as_view(),
|
||||||
name="evaluation-change-status"),
|
name="evaluation-change-status"),
|
||||||
path("archive/quick-evaluation/", ArchiveQuickEvaluationView.as_view(), name="quick-evaluation-archive"),
|
path("auto-evaluation-request/", AutoEvaluationRequestView.as_view(),
|
||||||
path("archive/evaluation-request/", ArchiveEvaluationrequestView.as_view(), name="evaluation-request-archive"),
|
name="evaluation-request-price-estimate"),
|
||||||
|
path("archived-evaluvation/", GetArchivedEvaluation.as_view(),
|
||||||
|
name="archived-evaluation"),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -13,4 +13,3 @@ from .valuation import * # noqa
|
|||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
from .didox import * # noqa
|
from .didox import * # noqa
|
||||||
from .tech_passport import * # noqa
|
from .tech_passport import * # noqa
|
||||||
from .certificate import * # noqa
|
|
||||||
|
|||||||
@@ -1,17 +1,20 @@
|
|||||||
|
import requests
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django_core.mixins import BaseViewSetMixin
|
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
from django_core.mixins import BaseViewSetMixin
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from drf_spectacular.utils import extend_schema, OpenApiParameter
|
from drf_spectacular.utils import extend_schema, OpenApiParameter
|
||||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||||
|
from rest_framework.generics import GenericAPIView, ListAPIView
|
||||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
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.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.accounts.serializers.user import UserSerializer
|
||||||
from core.apps.evaluation.filters.auto import AutoevaluationFilter
|
from core.apps.evaluation.filters.auto import AutoevaluationFilter
|
||||||
from core.apps.evaluation.models import AutoEvaluationModel
|
from core.apps.evaluation.models import AutoEvaluationModel
|
||||||
|
from core.apps.evaluation.serializers import AutoEvaluationSerializer
|
||||||
from core.apps.evaluation.serializers.auto import (
|
from core.apps.evaluation.serializers.auto import (
|
||||||
CreateAutoevaluationSerializer,
|
CreateAutoevaluationSerializer,
|
||||||
ListAutoevaluationSerializer,
|
ListAutoevaluationSerializer,
|
||||||
@@ -154,3 +157,39 @@ class AutoEvaluationListAppraisersView(GenericAPIView):
|
|||||||
return self.get_paginated_response(serializer.data)
|
return self.get_paginated_response(serializer.data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return Response({"error": str(e)}, status=500)
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
from django_core.mixins import BaseViewSetMixin
|
|
||||||
from drf_spectacular.utils import extend_schema
|
|
||||||
from rest_framework.permissions import IsAuthenticated
|
|
||||||
from rest_framework.viewsets import ModelViewSet
|
|
||||||
from core.apps.evaluation.models import CertificateModel
|
|
||||||
from core.apps.evaluation.serializers.certificate import BaseCertificateSerializer
|
|
||||||
from rest_framework.filters import SearchFilter
|
|
||||||
from rest_framework.parsers import MultiPartParser, FormParser
|
|
||||||
|
|
||||||
@extend_schema(tags=["Certificate"],request=BaseCertificateSerializer)
|
|
||||||
class CertificateView(BaseViewSetMixin, ModelViewSet):
|
|
||||||
queryset = CertificateModel.objects.all()
|
|
||||||
serializer_class = BaseCertificateSerializer
|
|
||||||
permission_classes = [IsAuthenticated]
|
|
||||||
|
|
||||||
parser_classes = [MultiPartParser, FormParser]
|
|
||||||
|
|
||||||
filter_backends = [SearchFilter]
|
|
||||||
search_fields = ["title"]
|
|
||||||
|
|
||||||
pagination_class = None
|
|
||||||
|
|
||||||
action_permission_classes = {}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import AllowAny
|
||||||
from rest_framework.generics import GenericAPIView
|
from rest_framework.generics import GenericAPIView
|
||||||
|
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ from core.services.didox import DidoxService
|
|||||||
|
|
||||||
class DidoxCompanyInfoAPIView(GenericAPIView):
|
class DidoxCompanyInfoAPIView(GenericAPIView):
|
||||||
authentication_classes = []
|
authentication_classes = []
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
@extend_schema(
|
@extend_schema(
|
||||||
tags=["Didox"],
|
tags=["Didox"],
|
||||||
@@ -31,6 +31,7 @@ class DidoxCompanyInfoAPIView(GenericAPIView):
|
|||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
tin = kwargs.get("tin")
|
tin = kwargs.get("tin")
|
||||||
|
|
||||||
|
# 🔥 TYPE CHECK
|
||||||
try:
|
try:
|
||||||
tin = int(tin)
|
tin = int(tin)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
@@ -47,14 +48,4 @@ class DidoxCompanyInfoAPIView(GenericAPIView):
|
|||||||
status=status.HTTP_502_BAD_GATEWAY
|
status=status.HTTP_502_BAD_GATEWAY
|
||||||
)
|
)
|
||||||
|
|
||||||
# if both name and personalNum are null/empty -> 404
|
|
||||||
name = data.get("name")
|
|
||||||
personal_num = data.get("personalNum")
|
|
||||||
|
|
||||||
if not name and not personal_num:
|
|
||||||
return Response(
|
|
||||||
{"detail": "Company or person not found"},
|
|
||||||
status=status.HTTP_404_NOT_FOUND
|
|
||||||
)
|
|
||||||
|
|
||||||
return Response(data, status=status.HTTP_200_OK)
|
return Response(data, status=status.HTTP_200_OK)
|
||||||
@@ -1,14 +1,10 @@
|
|||||||
from django_core.mixins import BaseViewSetMixin
|
from django_core.mixins import BaseViewSetMixin
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from drf_spectacular.utils import extend_schema, OpenApiResponse
|
from drf_spectacular.utils import extend_schema
|
||||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||||
from rest_framework.parsers import FormParser, MultiPartParser
|
from rest_framework.parsers import FormParser, MultiPartParser
|
||||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
from rest_framework.permissions import AllowAny
|
||||||
from rest_framework.viewsets import ModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
from rest_framework.generics import GenericAPIView
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from rest_framework import status
|
|
||||||
from django.shortcuts import get_object_or_404
|
|
||||||
|
|
||||||
from core.apps.evaluation.filters.quick import QuickevaluationFilter
|
from core.apps.evaluation.filters.quick import QuickevaluationFilter
|
||||||
from core.apps.evaluation.models import QuickEvaluationModel
|
from core.apps.evaluation.models import QuickEvaluationModel
|
||||||
@@ -16,7 +12,6 @@ from core.apps.evaluation.serializers.quick import (
|
|||||||
CreateQuickevaluationSerializer,
|
CreateQuickevaluationSerializer,
|
||||||
ListQuickevaluationSerializer,
|
ListQuickevaluationSerializer,
|
||||||
RetrieveQuickevaluationSerializer,
|
RetrieveQuickevaluationSerializer,
|
||||||
ArchiveQuickevaluationSerializer,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +20,7 @@ class QuickEvaluationView(BaseViewSetMixin, ModelViewSet):
|
|||||||
queryset = QuickEvaluationModel.objects.select_related(
|
queryset = QuickEvaluationModel.objects.select_related(
|
||||||
"created_by", "brand", "marka", "color", "fuel_type",
|
"created_by", "brand", "marka", "color", "fuel_type",
|
||||||
"body_type", "state_car", "car_position",
|
"body_type", "state_car", "car_position",
|
||||||
).filter(is_archive=False)
|
).all()
|
||||||
serializer_class = ListQuickevaluationSerializer
|
serializer_class = ListQuickevaluationSerializer
|
||||||
permission_classes = [AllowAny]
|
permission_classes = [AllowAny]
|
||||||
parser_classes = [MultiPartParser, FormParser]
|
parser_classes = [MultiPartParser, FormParser]
|
||||||
@@ -55,76 +50,3 @@ class QuickEvaluationView(BaseViewSetMixin, ModelViewSet):
|
|||||||
"retrieve": RetrieveQuickevaluationSerializer,
|
"retrieve": RetrieveQuickevaluationSerializer,
|
||||||
"create": CreateQuickevaluationSerializer,
|
"create": CreateQuickevaluationSerializer,
|
||||||
}
|
}
|
||||||
|
|
||||||
@extend_schema(tags=["QuickEvaluation"])
|
|
||||||
class ArchiveQuickEvaluationView(GenericAPIView):
|
|
||||||
permission_classes = [IsAuthenticated]
|
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
if self.request.method == "GET":
|
|
||||||
return ListQuickevaluationSerializer
|
|
||||||
return ArchiveQuickevaluationSerializer
|
|
||||||
|
|
||||||
@extend_schema(
|
|
||||||
tags=["QuickEvaluation"],
|
|
||||||
summary="Get archived quick evaluations list",
|
|
||||||
description="""
|
|
||||||
Returns only archived quick evaluations.
|
|
||||||
|
|
||||||
This endpoint works like quick-evaluation/,
|
|
||||||
but only records with is_archive=True are returned.
|
|
||||||
""",
|
|
||||||
responses={200: ListQuickevaluationSerializer(many=True)},
|
|
||||||
)
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
queryset = QuickEvaluationModel.objects.filter(
|
|
||||||
is_archive=True
|
|
||||||
).order_by("-created_at")
|
|
||||||
|
|
||||||
serializer = self.get_serializer(queryset, many=True)
|
|
||||||
|
|
||||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
@extend_schema(
|
|
||||||
tags=["QuickEvaluation"],
|
|
||||||
summary="Archive or unarchive quick evaluation",
|
|
||||||
description="""
|
|
||||||
Update archive status for quick evaluation.
|
|
||||||
|
|
||||||
- is_archive=true → archive
|
|
||||||
- is_archive=false → remove from archive
|
|
||||||
""",
|
|
||||||
request=ArchiveQuickevaluationSerializer,
|
|
||||||
responses={
|
|
||||||
200: OpenApiResponse(
|
|
||||||
description="Archive status updated successfully"
|
|
||||||
),
|
|
||||||
400: OpenApiResponse(
|
|
||||||
description="Validation error"
|
|
||||||
),
|
|
||||||
404: OpenApiResponse(
|
|
||||||
description="Quick evaluation not found"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
serializer = self.get_serializer(data=request.data)
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
|
|
||||||
validated_data = serializer.validated_data
|
|
||||||
|
|
||||||
obj = get_object_or_404(
|
|
||||||
QuickEvaluationModel,
|
|
||||||
id=validated_data["id"]
|
|
||||||
)
|
|
||||||
|
|
||||||
obj.is_archive = validated_data["is_archive"]
|
|
||||||
obj.save(update_fields=["is_archive"])
|
|
||||||
|
|
||||||
return Response(
|
|
||||||
{
|
|
||||||
"success": True,
|
|
||||||
"message": "Archive status updated successfully"
|
|
||||||
},
|
|
||||||
status=status.HTTP_200_OK
|
|
||||||
)
|
|
||||||
@@ -11,17 +11,15 @@ from rest_framework.response import Response
|
|||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
|
from core.apps.accounts.choices import RoleChoice
|
||||||
from core.apps.evaluation.filters.request import EvaluationrequestFilter
|
from core.apps.evaluation.filters.request import EvaluationrequestFilter
|
||||||
from core.apps.evaluation.models import EvaluationrequestModel
|
from core.apps.evaluation.models import EvaluationrequestModel
|
||||||
from core.apps.evaluation.serializers.request import (
|
from core.apps.evaluation.serializers.request import (
|
||||||
CreateEvaluationrequestSerializer,
|
CreateEvaluationrequestSerializer,
|
||||||
ListEvaluationrequestSerializer,
|
ListEvaluationrequestSerializer,
|
||||||
RetrieveEvaluationrequestSerializer,
|
RetrieveEvaluationrequestSerializer,
|
||||||
ArchiveEvaluationrequestSerializer,
|
|
||||||
)
|
)
|
||||||
from core.apps.evaluation.choices.request import RequestStatus
|
from core.apps.evaluation.choices.request import RequestStatus
|
||||||
from rest_framework.generics import GenericAPIView
|
|
||||||
from drf_spectacular.utils import OpenApiResponse
|
|
||||||
|
|
||||||
|
|
||||||
# class RequestPagination(PageNumberPagination):
|
# class RequestPagination(PageNumberPagination):
|
||||||
@@ -175,76 +173,3 @@ class EvaluationStatusChange(APIView):
|
|||||||
'status': evaluation.status,
|
'status': evaluation.status,
|
||||||
'id': evaluation.pk
|
'id': evaluation.pk
|
||||||
})
|
})
|
||||||
|
|
||||||
@extend_schema(tags=["EvaluationRequest"])
|
|
||||||
class ArchiveEvaluationrequestView(GenericAPIView):
|
|
||||||
permission_classes = [IsAuthenticated]
|
|
||||||
|
|
||||||
def get_serializer_class(self):
|
|
||||||
if self.request.method == "GET":
|
|
||||||
return ListEvaluationrequestSerializer
|
|
||||||
return ArchiveEvaluationrequestSerializer
|
|
||||||
|
|
||||||
@extend_schema(
|
|
||||||
tags=["EvaluationRequest"],
|
|
||||||
summary="Get archived evaluation requests list",
|
|
||||||
description="""
|
|
||||||
Returns only archived evaluation requests.
|
|
||||||
|
|
||||||
This endpoint works like evaluation-request/,
|
|
||||||
but only records with is_archive=True are returned.
|
|
||||||
""",
|
|
||||||
responses={200: ListEvaluationrequestSerializer(many=True)},
|
|
||||||
)
|
|
||||||
def get(self, request, *args, **kwargs):
|
|
||||||
queryset = EvaluationrequestModel.objects.filter(
|
|
||||||
is_archive=True
|
|
||||||
).order_by("-created_at")
|
|
||||||
|
|
||||||
serializer = self.get_serializer(queryset, many=True)
|
|
||||||
|
|
||||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
|
||||||
|
|
||||||
@extend_schema(
|
|
||||||
tags=["EvaluationRequest"],
|
|
||||||
summary="Archive or unarchive evaluation request",
|
|
||||||
description="""
|
|
||||||
Update archive status for evaluation request.
|
|
||||||
|
|
||||||
- is_archive=true → archive
|
|
||||||
- is_archive=false → remove from archive
|
|
||||||
""",
|
|
||||||
request=ArchiveEvaluationrequestSerializer,
|
|
||||||
responses={
|
|
||||||
200: OpenApiResponse(
|
|
||||||
description="Archive status updated successfully"
|
|
||||||
),
|
|
||||||
400: OpenApiResponse(
|
|
||||||
description="Validation error"
|
|
||||||
),
|
|
||||||
404: OpenApiResponse(
|
|
||||||
description="Evaluation request not found"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
def post(self, request, *args, **kwargs):
|
|
||||||
serializer = self.get_serializer(data=request.data)
|
|
||||||
serializer.is_valid(raise_exception=True)
|
|
||||||
|
|
||||||
validated_data = serializer.validated_data
|
|
||||||
|
|
||||||
obj = get_object_or_404(
|
|
||||||
EvaluationrequestModel,
|
|
||||||
id=validated_data["id"]
|
|
||||||
)
|
|
||||||
|
|
||||||
obj.is_archive = validated_data["is_archive"]
|
|
||||||
obj.save(update_fields=["is_archive"])
|
|
||||||
|
|
||||||
return Response(
|
|
||||||
{
|
|
||||||
"success": True,
|
|
||||||
"message": "Archive status updated successfully"
|
|
||||||
},
|
|
||||||
status=status.HTTP_200_OK
|
|
||||||
)
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.permissions import IsAuthenticated
|
from rest_framework.permissions import AllowAny
|
||||||
from rest_framework.generics import GenericAPIView
|
from rest_framework.generics import GenericAPIView
|
||||||
|
|
||||||
from drf_spectacular.utils import (
|
from drf_spectacular.utils import (
|
||||||
@@ -14,7 +14,7 @@ from ..serializers import TechPassportSerializer
|
|||||||
|
|
||||||
class TechPassportAPIView(GenericAPIView):
|
class TechPassportAPIView(GenericAPIView):
|
||||||
authentication_classes = []
|
authentication_classes = []
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
@extend_schema(
|
@extend_schema(
|
||||||
tags=["Tech Passport"],
|
tags=["Tech Passport"],
|
||||||
@@ -33,27 +33,18 @@ class TechPassportAPIView(GenericAPIView):
|
|||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
serializer = TechPassportSerializer(data=request.data)
|
serializer = TechPassportSerializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
data = serializer.validated_data
|
data = serializer.validated_data
|
||||||
|
|
||||||
result = TechPassportService.get_auto_info(
|
try:
|
||||||
autonumber=data["autonumber"],
|
result = TechPassportService.get_auto_info(
|
||||||
tech_pass_number=data["tech_pass_number"],
|
autonumber=data["autonumber"],
|
||||||
tech_pass_series=data["tech_pass_series"],
|
tech_pass_number=data["tech_pass_number"],
|
||||||
)
|
tech_pass_series=data["tech_pass_series"],
|
||||||
|
|
||||||
response_data = result["data"]
|
|
||||||
status_code = result["status_code"]
|
|
||||||
|
|
||||||
# success bo‘lsa faqat data ichidagi data qaytariladi
|
|
||||||
if status_code == 200:
|
|
||||||
return Response(
|
|
||||||
response_data.get("data", {}),
|
|
||||||
status=status.HTTP_200_OK
|
|
||||||
)
|
)
|
||||||
|
return Response(result, status=status.HTTP_200_OK)
|
||||||
|
|
||||||
# error bo‘lsa original response qaytariladi
|
except Exception as e:
|
||||||
return Response(
|
return Response(
|
||||||
response_data,
|
{"detail": str(e)},
|
||||||
status=status_code
|
status=status.HTTP_400_BAD_REQUEST
|
||||||
)
|
)
|
||||||
@@ -44,28 +44,21 @@ class TechPassportService:
|
|||||||
verify=False
|
verify=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Tech passport response status: {response.status_code}"
|
f"Tech passport info fetched successfully: {response.status_code}"
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
response_data = response.json()
|
||||||
response_data = response.json()
|
|
||||||
except ValueError:
|
|
||||||
response_data = {
|
|
||||||
"detail": "Invalid response from external service"
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return response_data.get("data", {})
|
||||||
"status_code": response.status_code,
|
|
||||||
"data": response_data
|
|
||||||
}
|
|
||||||
|
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
logger.error(str(e))
|
logger.error(
|
||||||
|
f"Error while fetching tech passport info: {str(e)}"
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
"status_code": 500,
|
"success": False,
|
||||||
"data": {
|
"message": str(e)
|
||||||
"detail": str(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ services:
|
|||||||
max-file: "5"
|
max-file: "5"
|
||||||
|
|
||||||
web:
|
web:
|
||||||
image: husanjon/sifatbaho:114
|
image: husanjon/sifatbaho:103
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
@@ -129,7 +129,7 @@ services:
|
|||||||
max-file: "5"
|
max-file: "5"
|
||||||
|
|
||||||
celery:
|
celery:
|
||||||
image: husanjon/sifatbaho:114
|
image: husanjon/sifatbaho:103
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
environment:
|
environment:
|
||||||
|
|||||||
Reference in New Issue
Block a user