12 Commits

Author SHA1 Message Date
komoliddin
3a08c81ff3 Add is_archive field to EvaluationRequest model. Write apis for update is_archive and list archived requests 2026-04-23 12:23:55 +05:00
github-actions[bot]
320f490d23 🔄 Update image to 107 [CI SKIP] 2026-04-22 10:03:44 +00:00
d4e6d80c86 Merge pull request 'deploy.yaml fixess' (#88) from fix/cicd-env into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 1m55s
Reviewed-on: #88
2026-04-22 10:02:12 +00:00
1f0e942be8 deploy.yaml fixess 2026-04-22 15:01:52 +05:00
github-actions[bot]
2af67333e2 🔄 Update image to 106 [CI SKIP] 2026-04-22 09:21:04 +00:00
81c689e7e9 Merge pull request 'feat: add 404 response for missing company or person in Didox API' (#86) from didox-api into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 1m56s
Reviewed-on: #86
2026-04-22 09:19:30 +00:00
github-actions[bot]
09d2e0954c 🔄 Update image to 105 [CI SKIP] 2026-04-22 09:17:53 +00:00
84a5afb2ee Merge pull request 'add request status change api' (#87) from shaxob into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 1m57s
Reviewed-on: #87
Reviewed-by: xoliqberdiyev <behruz@felixits.uz>
2026-04-22 09:16:19 +00:00
github-actions[bot]
cc8fc345d9 🔄 Update image to 104 [CI SKIP] 2026-04-22 09:11:31 +00:00
03e4387e4d Merge pull request 'fix: handle response errors and improve data return in TechPassportService' (#85) from tech-passport into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 2m16s
Reviewed-on: #85
Reviewed-by: xoliqberdiyev <behruz@felixits.uz>
2026-04-22 09:09:38 +00:00
komoliddin
01711b5927 feat: add 404 response for missing company or person in Didox API 2026-04-22 11:28:35 +05:00
komoliddin
33aa06f80b fix: handle response errors and improve data return in TechPassportService 2026-04-22 11:17:09 +05:00
19 changed files with 179 additions and 208 deletions

View File

@@ -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

View File

@@ -13,7 +13,7 @@ from config.env import env
def home(request): def home(request):
return HttpResponse("OK: #46c96214578b78c1fe731f9a2ceb4429b81d4da9") return HttpResponse("OK: #d4e6d80c86fcf4422f71238c6552dfa4b42f9737")
urlpatterns = [ urlpatterns = [

View File

@@ -3,7 +3,6 @@ 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):
@@ -18,7 +17,6 @@ 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)
permission = models.ForeignKey(Role, on_delete=models.SET_NULL, null=True)
USERNAME_FIELD = "phone" USERNAME_FIELD = "phone"
objects = UserManager() objects = UserManager()

View File

@@ -30,13 +30,3 @@ class UserUpdateSerializer(serializers.ModelSerializer):
"last_name", "last_name",
"avatar" "avatar"
] ]
class UserCreateSerializer(serializers.ModelSerializer):
class Meta:
model = get_user_model()
fields = [
"phone",
"first_name",
"last_name",
"password",
"role"
]

View File

@@ -4,8 +4,7 @@ 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, \ from .views import RegisterView, ResetPasswordView, MeView, ChangePasswordView, UserListApiView, AdminUserListApiView
AdminUpdateAPIView, AdminCreateAPIView
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
router = DefaultRouter() router = DefaultRouter()
@@ -26,6 +25,4 @@ 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/", AdminCreateAPIView.as_view(), name="user-create"),
path("admin/update/", AdminUpdateAPIView.as_view(), name="user-update"),
] ]

View File

@@ -1,17 +1,15 @@
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 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.response import Response
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.choices.user import RoleChoice
from core.apps.accounts.serializers.user import UserSerializer, UserCreateSerializer
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)
@@ -31,40 +29,3 @@ class AdminUserListApiView(generics.ListAPIView):
permission_classes = [IsAuthenticated] permission_classes = [IsAuthenticated]
filter_backends = [filters.SearchFilter] filter_backends = [filters.SearchFilter]
search_fields = ['phone', 'first_name', 'last_name'] search_fields = ['phone', 'first_name', 'last_name']
@extend_schema(tags=['User'],
responses={200: UserSerializer},
request=UserCreateSerializer)
class AdminCreateAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request):
if request.user.role not in (RoleChoice.SUPERUSER, RoleChoice.ADMIN):
return Response({'detail': 'Forbidden'}, status=403)
serializer = UserCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=201)
@extend_schema(tags=['User'],
responses={200: UserSerializer},
request=UserCreateSerializer)
class AdminUpdateAPIView(APIView):
permission_classes = [IsAuthenticated]
def put(self, request, pk):
if request.user.role not in (RoleChoice.SUPERUSER, RoleChoice.ADMIN):
return Response({'detail': 'Forbidden'}, status=403)
user = get_object_or_404(User, pk=pk)
serializer = UserCreateSerializer(user, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=200)

View File

@@ -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'),
),
]

View File

@@ -267,12 +267,6 @@ 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}"

View File

@@ -118,6 +118,10 @@ 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()}"

View File

@@ -1,60 +0,0 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from pydantic import BaseModel
class PermissionToAction(BaseModel):
name = models.CharField(max_length=200)
code = models.CharField(max_length=100, unique=True)
def __str__(self):
return f"{self.name} - {self.code}"
class Meta:
verbose_name = _('Harakatlar uchun ruxsatnoma')
verbose_name_plural = _('Harakatlar uchun ruxsatnomalar')
class PermissionToTab(BaseModel):
name = models.CharField(max_length=200)
code = models.CharField(max_length=100, unique=True)
permission_to_actions = models.ManyToManyField(
PermissionToAction, related_name='permission_to_tabs'
)
def __str__(self):
return f'{self.name} - {self.code}'
class Meta:
verbose_name = _("Bo'lim uchun ruxsatnoma")
verbose_name_plural = _("Bo'lim uchun ruxsatnomalar")
class Permission(BaseModel):
name = models.CharField(max_length=200)
code = models.CharField(max_length=100, unique=True)
permission_tab = models.ManyToManyField(PermissionToTab, related_name='permissions')
def __str__(self):
return f'{self.name} - {self.code}'
class Meta:
verbose_name = _('Sahifa uchun ruxsatnoma')
verbose_name_plural = _('Sahifa uchun ruxsatnomalar')
class Role(models.Model):
name = models.CharField(max_length=200, unique=True)
permissions = models.ManyToManyField(Permission, related_name='roles', blank=True)
permission_to_tabs = models.ManyToManyField(PermissionToTab, related_name='roles', blank=True)
permission_to_actions = models.ManyToManyField(
PermissionToAction, related_name='roles', blank=True
)
comment = models.CharField(max_length=200, null=True, blank=True)
def __str__(self):
return self.name
class Meta:
verbose_name = _('Rol')
verbose_name_plural = _('Rollar')

View File

@@ -1,20 +1,18 @@
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.choices.request import RequestStatus from core.apps.evaluation.models import AutoEvaluationModel,ReferenceitemModel, EvaluationrequestModel
from core.apps.evaluation.models import AutoEvaluationModel, ReferenceitemModel, EvaluationrequestModel
from core.apps.evaluation.serializers.reference import ListReferenceitemSerializer from core.apps.evaluation.serializers.reference import ListReferenceitemSerializer
from core.apps.evaluation.choices.request import RequestStatus
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, object_owner_type_display = serializers.CharField(source="get_object_owner_type_display", read_only=True, default=None)
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)
@@ -74,7 +72,6 @@ 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
# ) # )
@@ -144,6 +141,7 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer):
allow_null=True, allow_null=True,
) )
class Meta: class Meta:
model = AutoEvaluationModel model = AutoEvaluationModel
fields = [ fields = [
@@ -224,7 +222,6 @@ 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(),
@@ -257,6 +254,7 @@ class CreateAutoevaluationSerializer(serializers.ModelSerializer):
allow_null=True, allow_null=True,
) )
class Meta: class Meta:
model = AutoEvaluationModel model = AutoEvaluationModel
fields = [ fields = [
@@ -358,13 +356,3 @@ 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()

View File

@@ -55,6 +55,7 @@ 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):
@@ -183,3 +184,7 @@ 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)

View File

@@ -29,7 +29,7 @@ from .views import (
DidoxCompanyInfoAPIView, DidoxCompanyInfoAPIView,
TechPassportAPIView, TechPassportAPIView,
EvaluationStatusChange, EvaluationStatusChange,
GetArchivedEvaluationListAPIView ArchiveEvaluationrequestView,
) )
router = DefaultRouter() router = DefaultRouter()
@@ -60,8 +60,7 @@ urlpatterns = [
[ [
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(), path("<int:id>/remove/", AutoEvaluationRemoveAppraisersView.as_view(), name="auto-evaluation-remove-appraisers"),
name="auto-evaluation-remove-appraisers"),
] ]
)), )),
path( path(
@@ -76,10 +75,5 @@ 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("evaluation-request/archive/", 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(),
name="archived-evaluation"),
] ]

View File

@@ -1,14 +1,13 @@
from django.db.models import Q from django.db.models import Q
from django.shortcuts import get_object_or_404
from django_core.mixins import BaseViewSetMixin from django_core.mixins import BaseViewSetMixin
from django.shortcuts import get_object_or_404
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.response import Response
from rest_framework.views import APIView
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 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
@@ -155,22 +154,3 @@ 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"])
class GetArchivedEvaluationListAPIView(ListAPIView):
permission_classes = [IsAuthenticated]
def get_queryset(self):
return AutoEvaluationModel.objects.filter(is_archived=True)
@extend_schema(tags=["AutoEvaluation"])
class ArchivedEvaluation(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, pk):
auto_evaluation = get_object_or_404(AutoEvaluationModel, pk=pk)
auto_evaluation.is_archived = request.data["is_archived"]
auto_evaluation.save()
return Response({"success": True}, status=200)

View File

@@ -31,7 +31,6 @@ 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):
@@ -48,4 +47,14 @@ 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)

View File

@@ -1,23 +1,27 @@
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
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 from drf_spectacular.utils import extend_schema
from rest_framework import status
from rest_framework.filters import OrderingFilter, SearchFilter 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.response import Response
from rest_framework.views import APIView 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.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 rest_framework.generics import GenericAPIView
from drf_spectacular.utils import OpenApiResponse
# class RequestPagination(PageNumberPagination): # class RequestPagination(PageNumberPagination):
@@ -171,3 +175,76 @@ 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
)

View File

@@ -33,18 +33,27 @@ 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
try: result = TechPassportService.get_auto_info(
result = TechPassportService.get_auto_info( autonumber=data["autonumber"],
autonumber=data["autonumber"], tech_pass_number=data["tech_pass_number"],
tech_pass_number=data["tech_pass_number"], tech_pass_series=data["tech_pass_series"],
tech_pass_series=data["tech_pass_series"], )
)
return Response(result, status=status.HTTP_200_OK)
except Exception as e: response_data = result["data"]
status_code = result["status_code"]
# success bolsa faqat data ichidagi data qaytariladi
if status_code == 200:
return Response( return Response(
{"detail": str(e)}, response_data.get("data", {}),
status=status.HTTP_400_BAD_REQUEST status=status.HTTP_200_OK
) )
# error bolsa original response qaytariladi
return Response(
response_data,
status=status_code
)

View File

@@ -44,21 +44,28 @@ class TechPassportService:
verify=False verify=False
) )
response.raise_for_status()
logger.info( 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: except requests.exceptions.RequestException as e:
logger.error( logger.error(str(e))
f"Error while fetching tech passport info: {str(e)}"
)
return { return {
"success": False, "status_code": 500,
"message": str(e) "data": {
"detail": str(e)
}
} }

View File

@@ -84,7 +84,7 @@ services:
max-file: "5" max-file: "5"
web: web:
image: husanjon/sifatbaho:103 image: husanjon/sifatbaho:107
env_file: env_file:
- .env - .env
environment: environment:
@@ -129,7 +129,7 @@ services:
max-file: "5" max-file: "5"
celery: celery:
image: husanjon/sifatbaho:103 image: husanjon/sifatbaho:107
env_file: env_file:
- .env - .env
environment: environment: