Merge pull request 'feat: add search, filter, sort and pagination to QuickEvaluation list API' (#22) from feat/quick-evaluation-list-api into main
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 1m50s
All checks were successful
Deploy to Production / build-and-deploy (push) Successful in 1m50s
Reviewed-on: #22
This commit is contained in:
@@ -15,12 +15,18 @@ class QuickEvaluationAdmin(ModelAdmin):
|
||||
"manufacture_year",
|
||||
"condition",
|
||||
"estimated_price",
|
||||
"status",
|
||||
"car_type",
|
||||
"state_car",
|
||||
"created_at",
|
||||
)
|
||||
list_filter = (
|
||||
"fuel_type",
|
||||
"body_type",
|
||||
"condition",
|
||||
"status",
|
||||
"car_type",
|
||||
"state_car",
|
||||
)
|
||||
search_fields = (
|
||||
"brand",
|
||||
@@ -50,10 +56,11 @@ class QuickEvaluationAdmin(ModelAdmin):
|
||||
"fields": (
|
||||
("fuel_type", "body_type"),
|
||||
"condition",
|
||||
("car_type", "state_car"),
|
||||
),
|
||||
}),
|
||||
("Natija", {
|
||||
"fields": ("estimated_price",),
|
||||
"fields": ("estimated_price", "status"),
|
||||
}),
|
||||
("Tizim", {
|
||||
"classes": ("collapse",),
|
||||
|
||||
23
core/apps/evaluation/choices/quick.py
Normal file
23
core/apps/evaluation/choices/quick.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class QuickEvaluationStatus(models.TextChoices):
|
||||
CREATED = "created", _("Created")
|
||||
EVALUATOR_ASSIGNED = "evaluator_assigned", _("Evaluator assigned")
|
||||
EVALUATED = "evaluated", _("Evaluated")
|
||||
REJECTED = "rejected", _("Rejected")
|
||||
APPROVED = "approved", _("Approved")
|
||||
|
||||
|
||||
class CarType(models.TextChoices):
|
||||
LIGHTWEIGHT = "lightweight", _("Lightweight")
|
||||
TRUCK = "truck", _("Truck")
|
||||
BUS = "bus", _("Bus")
|
||||
MOTO = "moto", _("Moto")
|
||||
|
||||
|
||||
class CarState(models.TextChoices):
|
||||
GOOD = "good", _("Good")
|
||||
SATISFACTORY = "satisfactory", _("Satisfactory")
|
||||
BAD = "bad", _("Bad")
|
||||
@@ -8,6 +8,4 @@ class ValuationdocumentFilter(filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = ValuationDocumentModel
|
||||
fields = [
|
||||
"name",
|
||||
]
|
||||
fields = []
|
||||
|
||||
@@ -4,10 +4,28 @@ from core.apps.evaluation.models import QuickEvaluationModel
|
||||
|
||||
|
||||
class QuickevaluationFilter(filters.FilterSet):
|
||||
# name = filters.CharFilter(field_name="name", lookup_expr="icontains")
|
||||
status = filters.CharFilter(method="filter_status")
|
||||
car_type = filters.CharFilter(field_name="car_type", lookup_expr="exact")
|
||||
state_car = filters.CharFilter(field_name="state_car", lookup_expr="exact")
|
||||
created_from = filters.DateFilter(field_name="created_at", lookup_expr="gte")
|
||||
created_to = filters.DateFilter(field_name="created_at", lookup_expr="lte")
|
||||
year_from = filters.NumberFilter(field_name="manufacture_year", lookup_expr="gte")
|
||||
year_to = filters.NumberFilter(field_name="manufacture_year", lookup_expr="lte")
|
||||
|
||||
def filter_status(self, queryset, name, value):
|
||||
if value:
|
||||
statuses = [s.strip() for s in value.split(",") if s.strip()]
|
||||
return queryset.filter(status__in=statuses)
|
||||
return queryset
|
||||
|
||||
class Meta:
|
||||
model = QuickEvaluationModel
|
||||
fields = [
|
||||
"name",
|
||||
"status",
|
||||
"car_type",
|
||||
"state_car",
|
||||
"created_from",
|
||||
"created_to",
|
||||
"year_from",
|
||||
"year_to",
|
||||
]
|
||||
|
||||
@@ -8,6 +8,4 @@ class RealestateevaluationFilter(filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = RealEstateEvaluationModel
|
||||
fields = [
|
||||
"name",
|
||||
]
|
||||
fields = []
|
||||
|
||||
@@ -8,6 +8,4 @@ class EvaluationreportFilter(filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = EvaluationReportModel
|
||||
fields = [
|
||||
"name",
|
||||
]
|
||||
fields = []
|
||||
|
||||
@@ -8,6 +8,4 @@ class ValuationFilter(filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = ValuationModel
|
||||
fields = [
|
||||
"name",
|
||||
]
|
||||
fields = []
|
||||
|
||||
@@ -8,6 +8,4 @@ class VehicleFilter(filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = VehicleModel
|
||||
fields = [
|
||||
"name",
|
||||
]
|
||||
fields = []
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 5.2.7 on 2026-03-09 07:59
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('evaluation', '0009_valuationdocumentmodel'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='quickevaluationmodel',
|
||||
name='car_type',
|
||||
field=models.CharField(blank=True, choices=[('lightweight', 'Yengil avtomobil'), ('yuk', 'Yuk mashinasi'), ('bus', 'Avtobus'), ('moto', 'Mototsikl')], max_length=50, null=True, verbose_name='car type'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='quickevaluationmodel',
|
||||
name='state_car',
|
||||
field=models.CharField(blank=True, choices=[('yaxshi', 'Yaxshi'), ('qoniqarli', 'Qoniqarli'), ('yomon', 'Yomon')], max_length=50, null=True, verbose_name='car state'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='quickevaluationmodel',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('yaratildi', 'Yaratildi'), ('baxolovchi_biriktirildi', 'Baxolovchi biriktirildi'), ('baxolandi', 'Baxolandi'), ('rad_etildi', 'Rad etildi'), ('tasdiqlandi', 'Tasdiqlandi')], default='yaratildi', max_length=50, verbose_name='status'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,28 @@
|
||||
# Generated by Django 5.2.7 on 2026-03-09 08:10
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('evaluation', '0010_add_status_car_type_state_car_to_quick_evaluation'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='quickevaluationmodel',
|
||||
name='car_type',
|
||||
field=models.CharField(blank=True, choices=[('lightweight', 'Lightweight'), ('truck', 'Truck'), ('bus', 'Bus'), ('moto', 'Moto')], max_length=50, null=True, verbose_name='car type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='quickevaluationmodel',
|
||||
name='state_car',
|
||||
field=models.CharField(blank=True, choices=[('good', 'Good'), ('satisfactory', 'Satisfactory'), ('bad', 'Bad')], max_length=50, null=True, verbose_name='car state'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='quickevaluationmodel',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('created', 'Created'), ('evaluator_assigned', 'Evaluator assigned'), ('evaluated', 'Evaluated'), ('rejected', 'Rejected'), ('approved', 'Approved')], default='created', max_length=50, verbose_name='status'),
|
||||
),
|
||||
]
|
||||
@@ -3,8 +3,8 @@ from django.utils.translation import gettext_lazy as _
|
||||
from django_core.models import AbstractBaseModel
|
||||
from model_bakery import baker
|
||||
|
||||
|
||||
from core.apps.evaluation.choices.vehicle import FuelType, BodyType, VehicleCondition
|
||||
from core.apps.evaluation.choices.quick import CarState, CarType, QuickEvaluationStatus
|
||||
from core.apps.evaluation.choices.vehicle import BodyType, FuelType, VehicleCondition
|
||||
|
||||
|
||||
class QuickEvaluationModel(AbstractBaseModel):
|
||||
@@ -63,6 +63,26 @@ class QuickEvaluationModel(AbstractBaseModel):
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
status = models.CharField(
|
||||
verbose_name=_("status"),
|
||||
max_length=50,
|
||||
choices=QuickEvaluationStatus.choices,
|
||||
default=QuickEvaluationStatus.CREATED,
|
||||
)
|
||||
car_type = models.CharField(
|
||||
verbose_name=_("car type"),
|
||||
max_length=50,
|
||||
choices=CarType.choices,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
state_car = models.CharField(
|
||||
verbose_name=_("car state"),
|
||||
max_length=50,
|
||||
choices=CarState.choices,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"Quick Evaluation {self.pk} by {self.created_by}"
|
||||
|
||||
@@ -6,6 +6,9 @@ class BaseQuickevaluationSerializer(serializers.ModelSerializer):
|
||||
body_type_display = serializers.CharField(source="get_body_type_display", read_only=True)
|
||||
condition_display = serializers.CharField(source="get_condition_display", read_only=True)
|
||||
created_by_name = serializers.CharField(source="created_by.get_full_name", read_only=True)
|
||||
status_display = serializers.CharField(source="get_status_display", read_only=True)
|
||||
car_type_display = serializers.CharField(source="get_car_type_display", read_only=True)
|
||||
state_car_display = serializers.CharField(source="get_state_car_display", read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = QuickEvaluationModel
|
||||
@@ -18,6 +21,12 @@ class BaseQuickevaluationSerializer(serializers.ModelSerializer):
|
||||
"license_plate",
|
||||
"manufacture_year",
|
||||
"estimated_price",
|
||||
"status",
|
||||
"status_display",
|
||||
"car_type",
|
||||
"car_type_display",
|
||||
"state_car",
|
||||
"state_car_display",
|
||||
"created_at",
|
||||
]
|
||||
|
||||
@@ -57,4 +66,6 @@ class CreateQuickevaluationSerializer(BaseQuickevaluationSerializer):
|
||||
"fuel_type",
|
||||
"body_type",
|
||||
"condition",
|
||||
"car_type",
|
||||
"state_car",
|
||||
]
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
from django_core.mixins import BaseViewSetMixin
|
||||
from django_filters.rest_framework import DjangoFilterBackend
|
||||
from drf_spectacular.utils import extend_schema
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.permissions import AllowAny
|
||||
from rest_framework.viewsets import ReadOnlyModelViewSet
|
||||
|
||||
from core.apps.evaluation.filters.quick import QuickevaluationFilter
|
||||
from core.apps.evaluation.models import QuickEvaluationModel
|
||||
from core.apps.evaluation.serializers.quick import (
|
||||
CreateQuickevaluationSerializer,
|
||||
@@ -13,10 +16,29 @@ from core.apps.evaluation.serializers.quick import (
|
||||
|
||||
@extend_schema(tags=["QuickEvaluation"])
|
||||
class QuickEvaluationView(BaseViewSetMixin, ReadOnlyModelViewSet):
|
||||
queryset = QuickEvaluationModel.objects.all()
|
||||
queryset = QuickEvaluationModel.objects.select_related("created_by").all()
|
||||
serializer_class = ListQuickevaluationSerializer
|
||||
permission_classes = [AllowAny]
|
||||
|
||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||
filterset_class = QuickevaluationFilter
|
||||
search_fields = ["license_plate", "model", "brand"]
|
||||
ordering_fields = [
|
||||
"created_at",
|
||||
"updated_at",
|
||||
"license_plate",
|
||||
"brand",
|
||||
"model",
|
||||
"car_type",
|
||||
"manufacture_year",
|
||||
"color",
|
||||
"fuel_type",
|
||||
"state_car",
|
||||
"status",
|
||||
"mileage",
|
||||
]
|
||||
ordering = ["-created_at"]
|
||||
|
||||
action_permission_classes = {}
|
||||
action_serializer_class = {
|
||||
"list": ListQuickevaluationSerializer,
|
||||
|
||||
Reference in New Issue
Block a user