Compare commits
36 Commits
84cc11fe2a
...
3fd0f9959b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fd0f9959b | ||
|
|
c89f2b32af | ||
| 88dedd85c7 | |||
|
|
fb275a091a | ||
|
|
190480b6f7 | ||
| 1a985ffa4b | |||
|
|
3b62c5a7bf | ||
|
|
07f8d55966 | ||
| b0b4ccfeee | |||
|
|
ccefe9c119 | ||
|
|
6456283f72 | ||
|
|
6eed2d998e | ||
| 2c82691166 | |||
|
|
7a88e39b96 | ||
|
|
dc622ce305 | ||
|
|
6e0718c5db | ||
|
|
32d3bea234 | ||
|
|
129827b495 | ||
|
|
50cc555783 | ||
|
|
76563b3ef0 | ||
|
|
207363dc6a | ||
| 2a08ad9662 | |||
|
|
5cf4b950fb | ||
|
|
3a08c81ff3 | ||
|
|
4fee037467 | ||
|
|
320f490d23 | ||
| d4e6d80c86 | |||
| 1f0e942be8 | |||
|
|
2af67333e2 | ||
| 81c689e7e9 | |||
|
|
09d2e0954c | ||
| 84a5afb2ee | |||
|
|
cc8fc345d9 | ||
| 03e4387e4d | |||
|
|
01711b5927 | ||
|
|
33aa06f80b |
4
.github/workflows/deploy.yaml
vendored
4
.github/workflows/deploy.yaml
vendored
@@ -153,7 +153,7 @@ jobs:
|
||||
update_env \
|
||||
"DB_HOST=postgres" \
|
||||
"DB_NAME=sifatbahodb" \
|
||||
"DB_PORT=5432"
|
||||
|
||||
"DB_PORT=5432" \
|
||||
"DIDOX_TOKEN=${{ secrets.DIDOX_TOKEN }}"
|
||||
export PORT=8085
|
||||
docker stack deploy -c stack.yaml ${{ env.PROJECT_NAME }} --with-registry-auth
|
||||
|
||||
@@ -13,7 +13,7 @@ from config.env import env
|
||||
|
||||
|
||||
def home(request):
|
||||
return HttpResponse("OK: #46c96214578b78c1fe731f9a2ceb4429b81d4da9")
|
||||
return HttpResponse("OK: #88dedd85c79ccf732b2adac03616bd14e67a1579")
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
@@ -30,6 +30,22 @@ class UserUpdateSerializer(serializers.ModelSerializer):
|
||||
"last_name",
|
||||
"avatar"
|
||||
]
|
||||
|
||||
class AdminUserSerializer(serializers.ModelSerializer):
|
||||
avatar = serializers.SerializerMethodField(method_name='get_avatar')
|
||||
|
||||
class Meta:
|
||||
model = get_user_model()
|
||||
fields = "__all__"
|
||||
|
||||
def get_avatar(self, obj):
|
||||
request = self.context.get('request')
|
||||
if obj.avatar:
|
||||
return request.build_absolute_uri(obj.avatar.url)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
class UserCreateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = get_user_model()
|
||||
@@ -38,5 +54,4 @@ class UserCreateSerializer(serializers.ModelSerializer):
|
||||
"first_name",
|
||||
"last_name",
|
||||
"password",
|
||||
"role"
|
||||
]
|
||||
"role"]
|
||||
@@ -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, \
|
||||
AdminUpdateAPIView, AdminCreateAPIView
|
||||
AdminUserView, AdminCreateAPIView, AdminUpdateAPIView
|
||||
from rest_framework.routers import DefaultRouter
|
||||
|
||||
router = DefaultRouter()
|
||||
@@ -13,6 +13,7 @@ router.register("auth", RegisterView, basename="auth")
|
||||
router.register("auth", ResetPasswordView, basename="reset-password")
|
||||
router.register("auth", MeView, basename="me")
|
||||
router.register("auth", ChangePasswordView, basename="change-password")
|
||||
router.register("user", AdminUserView, basename="user-crud")
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django_core.mixins import BaseViewSetMixin
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from rest_framework import generics, filters
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from core.apps.accounts.choices.user import RoleChoice
|
||||
from core.apps.accounts.serializers.user import UserSerializer, UserCreateSerializer
|
||||
from core.apps.accounts.serializers.user import UserSerializer, AdminUserSerializer, UserCreateSerializer
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@@ -33,6 +35,18 @@ class AdminUserListApiView(generics.ListAPIView):
|
||||
search_fields = ['phone', 'first_name', 'last_name']
|
||||
|
||||
|
||||
@extend_schema(tags=["User"], request=AdminUserSerializer)
|
||||
class AdminUserView(BaseViewSetMixin, ModelViewSet):
|
||||
queryset = User.objects.filter(role=RoleChoice.USER)
|
||||
serializer_class = AdminUserSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
filter_backends = [filters.SearchFilter]
|
||||
search_fields = ['phone', 'first_name', 'last_name']
|
||||
|
||||
def serializer_context(self):
|
||||
return self.serializer_class(context={"request": self.request})
|
||||
|
||||
|
||||
@extend_schema(tags=['User'],
|
||||
responses={200: UserSerializer},
|
||||
request=UserCreateSerializer)
|
||||
@@ -49,10 +63,10 @@ class AdminCreateAPIView(APIView):
|
||||
|
||||
return Response(serializer.data, status=201)
|
||||
|
||||
|
||||
@extend_schema(tags=['User'],
|
||||
responses={200: UserSerializer},
|
||||
request=UserCreateSerializer)
|
||||
|
||||
class AdminUpdateAPIView(APIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@@ -66,5 +80,3 @@ class AdminUpdateAPIView(APIView):
|
||||
serializer.save()
|
||||
|
||||
return Response(serializer.data, status=200)
|
||||
|
||||
|
||||
|
||||
28
core/apps/evaluation/migrations/0032_certificatemodel.py
Normal file
28
core/apps/evaluation/migrations/0032_certificatemodel.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# 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',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# 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'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# 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'),
|
||||
),
|
||||
]
|
||||
15
core/apps/evaluation/migrations/0033_merge_20260423_1622.py
Normal file
15
core/apps/evaluation/migrations/0033_merge_20260423_1622.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# 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 = [
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
# 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,3 +11,4 @@ from .report import * # noqa
|
||||
from .request import * # noqa
|
||||
from .valuation import * # noqa
|
||||
from .vehicle import * # noqa
|
||||
from .certificate import * # noqa
|
||||
|
||||
30
core/apps/evaluation/models/certificate.py
Normal file
30
core/apps/evaluation/models/certificate.py
Normal file
@@ -0,0 +1,30 @@
|
||||
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,6 +132,11 @@ class QuickEvaluationModel(AbstractBaseModel):
|
||||
default=QuickEvaluationStatus.CREATED,
|
||||
)
|
||||
|
||||
is_archive = models.BooleanField(
|
||||
verbose_name=_("is archive"),
|
||||
default=False,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"Quick Evaluation {self.pk} by {self.created_by}"
|
||||
|
||||
|
||||
@@ -118,6 +118,10 @@ class EvaluationrequestModel(AbstractBaseModel):
|
||||
choices=RequestStatus.choices,
|
||||
default=RequestStatus.PENDING,
|
||||
)
|
||||
is_archive = models.BooleanField(
|
||||
verbose_name=_("is archive"),
|
||||
default=False,
|
||||
)
|
||||
def __str__(self):
|
||||
return f"Requests #{self.pk} — {self.get_rate_type_display()}"
|
||||
|
||||
|
||||
@@ -12,3 +12,4 @@ from .request import * # noqa
|
||||
from .valuation import * # noqa
|
||||
from .vehicle import * # noqa
|
||||
from .tech_passport import * # noqa
|
||||
from .certificate import * # noqa
|
||||
|
||||
1
core/apps/evaluation/serializers/certificate/__init__.py
Normal file
1
core/apps/evaluation/serializers/certificate/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .certificate import * # noqa
|
||||
13
core/apps/evaluation/serializers/certificate/certificate.py
Normal file
13
core/apps/evaluation/serializers/certificate/certificate.py
Normal file
@@ -0,0 +1,13 @@
|
||||
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,7 +38,8 @@ class BaseQuickevaluationSerializer(serializers.ModelSerializer):
|
||||
"state_car_name",
|
||||
"created_at",
|
||||
"distance_covered",
|
||||
"tex_passport_serie_num"
|
||||
"tex_passport_serie_num",
|
||||
"is_archive"
|
||||
]
|
||||
|
||||
|
||||
@@ -125,3 +126,8 @@ class CreateQuickevaluationSerializer(serializers.ModelSerializer):
|
||||
if request and request.user and request.user.is_authenticated:
|
||||
validated_data["created_by"] = request.user
|
||||
return super().create(validated_data)
|
||||
|
||||
|
||||
class ArchiveQuickevaluationSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField(required=True)
|
||||
is_archive = serializers.BooleanField(required=True)
|
||||
@@ -55,6 +55,7 @@ class BaseEvaluationrequestSerializer(serializers.ModelSerializer):
|
||||
"user",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"is_archive",
|
||||
]
|
||||
|
||||
def get_location(self, obj):
|
||||
@@ -183,3 +184,7 @@ class CreateEvaluationrequestSerializer(serializers.ModelSerializer):
|
||||
validated_data["location_name"] = str(location_name)
|
||||
validated_data["user"] = self.context["request"].user
|
||||
return super().create(validated_data)
|
||||
|
||||
class ArchiveEvaluationrequestSerializer(serializers.Serializer):
|
||||
id = serializers.IntegerField(required=True)
|
||||
is_archive = serializers.BooleanField(required=True)
|
||||
@@ -29,7 +29,9 @@ from .views import (
|
||||
DidoxCompanyInfoAPIView,
|
||||
TechPassportAPIView,
|
||||
EvaluationStatusChange,
|
||||
GetArchivedEvaluationListAPIView
|
||||
CertificateView,
|
||||
ArchiveQuickEvaluationView,
|
||||
ArchiveEvaluationrequestView, GetArchivedEvaluationListAPIView, ArchivedEvaluation,
|
||||
)
|
||||
|
||||
router = DefaultRouter()
|
||||
@@ -54,14 +56,14 @@ 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("certificate", CertificateView, basename="certificate")
|
||||
urlpatterns = [
|
||||
path("", include(router.urls)),
|
||||
path("auto-evaluation/appraisers/", include(
|
||||
[
|
||||
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>/remove/", AutoEvaluationRemoveAppraisersView.as_view(),
|
||||
name="auto-evaluation-remove-appraisers"),
|
||||
path("<int:id>/remove/", AutoEvaluationRemoveAppraisersView.as_view(), name="auto-evaluation-remove-appraisers"),
|
||||
]
|
||||
)),
|
||||
path(
|
||||
@@ -76,10 +78,13 @@ urlpatterns = [
|
||||
),
|
||||
path("evaluation-request/<int:pk>/change-status/", EvaluationStatusChange.as_view(),
|
||||
name="evaluation-change-status"),
|
||||
path("archive/quick-evaluation/", ArchiveQuickEvaluationView.as_view(), name="quick-evaluation-archive"),
|
||||
path("archive/evaluation-request/", ArchiveEvaluationrequestView.as_view(), name="evaluation-request-archive"),
|
||||
|
||||
path("archived-evaluvation/", GetArchivedEvaluationListAPIView.as_view(),
|
||||
name="archived-evaluation"),
|
||||
|
||||
path("auto-evaluvation-change-status/<int:pk>", GetArchivedEvaluationListAPIView.as_view(),
|
||||
path("auto-evaluvation-change-status/<int:pk>", ArchivedEvaluation.as_view(),
|
||||
name="archived-evaluation"),
|
||||
|
||||
]
|
||||
|
||||
@@ -13,3 +13,4 @@ from .valuation import * # noqa
|
||||
from .vehicle import * # noqa
|
||||
from .didox import * # noqa
|
||||
from .tech_passport import * # noqa
|
||||
from .certificate import * # noqa
|
||||
|
||||
@@ -160,7 +160,6 @@ class AutoEvaluationListAppraisersView(GenericAPIView):
|
||||
@extend_schema(tags=["AutoEvaluation"])
|
||||
class GetArchivedEvaluationListAPIView(ListAPIView):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
return AutoEvaluationModel.objects.filter(is_archived=True)
|
||||
|
||||
|
||||
23
core/apps/evaluation/views/certificate.py
Normal file
23
core/apps/evaluation/views/certificate.py
Normal file
@@ -0,0 +1,23 @@
|
||||
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 import status
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.generics import GenericAPIView
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from core.services.didox import DidoxService
|
||||
|
||||
class DidoxCompanyInfoAPIView(GenericAPIView):
|
||||
authentication_classes = []
|
||||
permission_classes = [AllowAny]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@extend_schema(
|
||||
tags=["Didox"],
|
||||
@@ -31,7 +31,6 @@ class DidoxCompanyInfoAPIView(GenericAPIView):
|
||||
def get(self, request, *args, **kwargs):
|
||||
tin = kwargs.get("tin")
|
||||
|
||||
# 🔥 TYPE CHECK
|
||||
try:
|
||||
tin = int(tin)
|
||||
except (TypeError, ValueError):
|
||||
@@ -48,4 +47,14 @@ class DidoxCompanyInfoAPIView(GenericAPIView):
|
||||
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)
|
||||
@@ -1,10 +1,14 @@
|
||||
from django_core.mixins import BaseViewSetMixin
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from drf_spectacular.utils import extend_schema, OpenApiResponse
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.parsers import FormParser, MultiPartParser
|
||||
from rest_framework.permissions import AllowAny
|
||||
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 import status
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from core.apps.evaluation.filters.quick import QuickevaluationFilter
|
||||
from core.apps.evaluation.models import QuickEvaluationModel
|
||||
@@ -12,6 +16,7 @@ from core.apps.evaluation.serializers.quick import (
|
||||
CreateQuickevaluationSerializer,
|
||||
ListQuickevaluationSerializer,
|
||||
RetrieveQuickevaluationSerializer,
|
||||
ArchiveQuickevaluationSerializer,
|
||||
)
|
||||
|
||||
|
||||
@@ -20,7 +25,7 @@ class QuickEvaluationView(BaseViewSetMixin, ModelViewSet):
|
||||
queryset = QuickEvaluationModel.objects.select_related(
|
||||
"created_by", "brand", "marka", "color", "fuel_type",
|
||||
"body_type", "state_car", "car_position",
|
||||
).all()
|
||||
).filter(is_archive=False)
|
||||
serializer_class = ListQuickevaluationSerializer
|
||||
permission_classes = [AllowAny]
|
||||
parser_classes = [MultiPartParser, FormParser]
|
||||
@@ -50,3 +55,76 @@ class QuickEvaluationView(BaseViewSetMixin, ModelViewSet):
|
||||
"retrieve": RetrieveQuickevaluationSerializer,
|
||||
"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
|
||||
)
|
||||
@@ -1,23 +1,27 @@
|
||||
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.permissions import IsAuthenticated
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from rest_framework.permissions import AllowAny, IsAuthenticated
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from rest_framework import status
|
||||
|
||||
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 (
|
||||
CreateEvaluationrequestSerializer,
|
||||
ListEvaluationrequestSerializer,
|
||||
RetrieveEvaluationrequestSerializer,
|
||||
ArchiveEvaluationrequestSerializer,
|
||||
)
|
||||
from core.apps.evaluation.choices.request import RequestStatus
|
||||
from rest_framework.generics import GenericAPIView
|
||||
from drf_spectacular.utils import OpenApiResponse
|
||||
|
||||
|
||||
# class RequestPagination(PageNumberPagination):
|
||||
@@ -170,4 +174,77 @@ class EvaluationStatusChange(APIView):
|
||||
'success': True,
|
||||
'status': evaluation.status,
|
||||
'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 import status
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.generics import GenericAPIView
|
||||
|
||||
from drf_spectacular.utils import (
|
||||
@@ -14,7 +14,7 @@ from ..serializers import TechPassportSerializer
|
||||
|
||||
class TechPassportAPIView(GenericAPIView):
|
||||
authentication_classes = []
|
||||
permission_classes = [AllowAny]
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
@extend_schema(
|
||||
tags=["Tech Passport"],
|
||||
@@ -33,18 +33,27 @@ class TechPassportAPIView(GenericAPIView):
|
||||
def post(self, request, *args, **kwargs):
|
||||
serializer = TechPassportSerializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
data = serializer.validated_data
|
||||
|
||||
try:
|
||||
result = TechPassportService.get_auto_info(
|
||||
autonumber=data["autonumber"],
|
||||
tech_pass_number=data["tech_pass_number"],
|
||||
tech_pass_series=data["tech_pass_series"],
|
||||
)
|
||||
return Response(result, status=status.HTTP_200_OK)
|
||||
result = TechPassportService.get_auto_info(
|
||||
autonumber=data["autonumber"],
|
||||
tech_pass_number=data["tech_pass_number"],
|
||||
tech_pass_series=data["tech_pass_series"],
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
response_data = result["data"]
|
||||
status_code = result["status_code"]
|
||||
|
||||
# success bo‘lsa faqat data ichidagi data qaytariladi
|
||||
if status_code == 200:
|
||||
return Response(
|
||||
{"detail": str(e)},
|
||||
status=status.HTTP_400_BAD_REQUEST
|
||||
)
|
||||
response_data.get("data", {}),
|
||||
status=status.HTTP_200_OK
|
||||
)
|
||||
|
||||
# error bo‘lsa original response qaytariladi
|
||||
return Response(
|
||||
response_data,
|
||||
status=status_code
|
||||
)
|
||||
@@ -44,21 +44,28 @@ class TechPassportService:
|
||||
verify=False
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
|
||||
logger.info(
|
||||
f"Tech passport info fetched successfully: {response.status_code}"
|
||||
f"Tech passport response status: {response.status_code}"
|
||||
)
|
||||
|
||||
response_data = response.json()
|
||||
try:
|
||||
response_data = response.json()
|
||||
except ValueError:
|
||||
response_data = {
|
||||
"detail": "Invalid response from external service"
|
||||
}
|
||||
|
||||
return response_data.get("data", {})
|
||||
return {
|
||||
"status_code": response.status_code,
|
||||
"data": response_data
|
||||
}
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(
|
||||
f"Error while fetching tech passport info: {str(e)}"
|
||||
)
|
||||
logger.error(str(e))
|
||||
|
||||
return {
|
||||
"success": False,
|
||||
"message": str(e)
|
||||
"status_code": 500,
|
||||
"data": {
|
||||
"detail": str(e)
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ services:
|
||||
max-file: "5"
|
||||
|
||||
web:
|
||||
image: husanjon/sifatbaho:103
|
||||
image: husanjon/sifatbaho:115
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
@@ -129,7 +129,7 @@ services:
|
||||
max-file: "5"
|
||||
|
||||
celery:
|
||||
image: husanjon/sifatbaho:103
|
||||
image: husanjon/sifatbaho:115
|
||||
env_file:
|
||||
- .env
|
||||
environment:
|
||||
|
||||
Reference in New Issue
Block a user