From 93757b0342d7f954b0b2725fe26aca1b2c888bf9 Mon Sep 17 00:00:00 2001 From: Husanjonazamov Date: Tue, 10 Mar 2026 14:02:43 +0500 Subject: [PATCH] user ariza uchun requesty yaratish uchun api chiqarildi --- config/conf/navigation.py | 5 + core/apps/evaluation/admin/__init__.py | 1 + core/apps/evaluation/admin/request.py | 63 +++++++++ core/apps/evaluation/choices/request.py | 21 +++ core/apps/evaluation/filters/__init__.py | 1 + core/apps/evaluation/filters/request.py | 35 +++++ core/apps/evaluation/forms/__init__.py | 1 + core/apps/evaluation/forms/request.py | 10 ++ .../migrations/0018_evaluationrequestmodel.py | 45 ++++++ core/apps/evaluation/models/__init__.py | 1 + core/apps/evaluation/models/request.py | 119 ++++++++++++++++ core/apps/evaluation/permissions/__init__.py | 1 + core/apps/evaluation/permissions/request.py | 12 ++ core/apps/evaluation/serializers/__init__.py | 1 + .../serializers/request/EvaluationRequest.py | 132 ++++++++++++++++++ .../serializers/request/__init__.py | 1 + core/apps/evaluation/signals/__init__.py | 1 + core/apps/evaluation/signals/request.py | 27 ++++ core/apps/evaluation/tests/__init__.py | 1 + .../apps/evaluation/tests/request/__init__.py | 1 + .../tests/request/test_EvaluationRequest.py | 101 ++++++++++++++ core/apps/evaluation/translation/__init__.py | 1 + core/apps/evaluation/translation/request.py | 8 ++ core/apps/evaluation/urls.py | 2 + core/apps/evaluation/validators/__init__.py | 1 + core/apps/evaluation/validators/request.py | 8 ++ core/apps/evaluation/views/__init__.py | 1 + core/apps/evaluation/views/request.py | 56 ++++++++ 28 files changed, 657 insertions(+) create mode 100644 core/apps/evaluation/admin/request.py create mode 100644 core/apps/evaluation/choices/request.py create mode 100644 core/apps/evaluation/filters/request.py create mode 100644 core/apps/evaluation/forms/request.py create mode 100644 core/apps/evaluation/migrations/0018_evaluationrequestmodel.py create mode 100644 core/apps/evaluation/models/request.py create mode 100644 core/apps/evaluation/permissions/request.py create mode 100644 core/apps/evaluation/serializers/request/EvaluationRequest.py create mode 100644 core/apps/evaluation/serializers/request/__init__.py create mode 100644 core/apps/evaluation/signals/request.py create mode 100644 core/apps/evaluation/tests/request/__init__.py create mode 100644 core/apps/evaluation/tests/request/test_EvaluationRequest.py create mode 100644 core/apps/evaluation/translation/request.py create mode 100644 core/apps/evaluation/validators/request.py create mode 100644 core/apps/evaluation/views/request.py diff --git a/config/conf/navigation.py b/config/conf/navigation.py index 2ec00e5..08788cc 100644 --- a/config/conf/navigation.py +++ b/config/conf/navigation.py @@ -48,6 +48,11 @@ PAGES = [ "title": _("Arizalar"), "separator": True, "items": [ + { + "title": _("Baholash so'rovlari"), + "icon": "rate_review", + "link": reverse_lazy("admin:evaluation_evaluationrequestmodel_changelist"), + }, { "title": _("Barcha arizalar"), "icon": "description", diff --git a/core/apps/evaluation/admin/__init__.py b/core/apps/evaluation/admin/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/admin/__init__.py +++ b/core/apps/evaluation/admin/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/admin/request.py b/core/apps/evaluation/admin/request.py new file mode 100644 index 0000000..8a80579 --- /dev/null +++ b/core/apps/evaluation/admin/request.py @@ -0,0 +1,63 @@ +from django.contrib import admin +from unfold.admin import ModelAdmin + +from core.apps.evaluation.models import EvaluationrequestModel + + +@admin.register(EvaluationrequestModel) +class EvaluationrequestAdmin(ModelAdmin): + list_display = ( + "id", + "user", + "rate_type", + "object_type", + "customer_inn_number", + "owner_inn_number", + "status", + "need_delivering", + "created_at", + ) + list_filter = ("status", "rate_type", "object_type", "need_delivering") + search_fields = ( + "customer_inn_number", + "owner_inn_number", + "tex_passport", + "user__phone", + ) + readonly_fields = ("user", "created_at", "updated_at") + fieldsets = ( + ("Asosiy", { + "fields": ( + "user", + "rate_type", + "object_type", + "status", + ), + }), + ("Buyurtmachi", { + "fields": ( + ("customer_inn_number", "owner_inn_number"), + "tex_passport", + ), + }), + ("Baholash parametrlari", { + "fields": ( + ("value_determined", "rate_goal"), + ("property_rights", "form_ownership"), + ), + }), + ("Qo'shimcha (truck_car)", { + "classes": ("collapse",), + "fields": ("worked_hours", "chassi"), + }), + ("Yetkazish", { + "fields": ( + "need_delivering", + ("location_lat", "location_lng"), + ), + }), + ("Tizim", { + "classes": ("collapse",), + "fields": ("created_at", "updated_at"), + }), + ) diff --git a/core/apps/evaluation/choices/request.py b/core/apps/evaluation/choices/request.py new file mode 100644 index 0000000..b0efa46 --- /dev/null +++ b/core/apps/evaluation/choices/request.py @@ -0,0 +1,21 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class EvaluationRateType(models.TextChoices): + AUTO = "auto", _("Automobil") + REAL_ESTATE = "real_estate", _("Ko'chmas mulk") + EQUIPMENT = "equipment", _("Uskuna") + + +class RequestObjectType(models.TextChoices): + LIGHTWEIGHT_AUTO = "lightweight_auto", _("Yengil automobil") + TRUCK_CAR = "truck_car", _("Yuk automobil") + SPECIAL_TECH = "special_tech", _("Maxsus texnika") + + +class RequestStatus(models.TextChoices): + PENDING = "pending", _("Kutilmoqda") + IN_PROGRESS = "in_progress", _("Jarayonda") + COMPLETED = "completed", _("Bajarildi") + REJECTED = "rejected", _("Rad etildi") diff --git a/core/apps/evaluation/filters/__init__.py b/core/apps/evaluation/filters/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/filters/__init__.py +++ b/core/apps/evaluation/filters/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/filters/request.py b/core/apps/evaluation/filters/request.py new file mode 100644 index 0000000..1830e3c --- /dev/null +++ b/core/apps/evaluation/filters/request.py @@ -0,0 +1,35 @@ +from django_filters import rest_framework as filters + +from core.apps.evaluation.models import EvaluationrequestModel + + +class EvaluationrequestFilter(filters.FilterSet): + rate_type = filters.CharFilter(field_name="rate_type", lookup_expr="exact") + object_type = filters.CharFilter(field_name="object_type", lookup_expr="exact") + status = filters.CharFilter(field_name="status", lookup_expr="exact") + need_delivering = filters.BooleanFilter(field_name="need_delivering") + customer_inn_number = filters.CharFilter( + field_name="customer_inn_number", lookup_expr="icontains" + ) + owner_inn_number = filters.CharFilter( + field_name="owner_inn_number", lookup_expr="icontains" + ) + tex_passport = filters.CharFilter( + field_name="tex_passport", lookup_expr="icontains" + ) + date_from = filters.DateFilter(field_name="created_at", lookup_expr="gte") + date_to = filters.DateFilter(field_name="created_at", lookup_expr="lte") + + class Meta: + model = EvaluationrequestModel + fields = [ + "rate_type", + "object_type", + "status", + "need_delivering", + "customer_inn_number", + "owner_inn_number", + "tex_passport", + "date_from", + "date_to", + ] diff --git a/core/apps/evaluation/forms/__init__.py b/core/apps/evaluation/forms/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/forms/__init__.py +++ b/core/apps/evaluation/forms/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/forms/request.py b/core/apps/evaluation/forms/request.py new file mode 100644 index 0000000..57b8e04 --- /dev/null +++ b/core/apps/evaluation/forms/request.py @@ -0,0 +1,10 @@ +from django import forms + +from core.apps.evaluation.models import EvaluationrequestModel + + +class EvaluationrequestForm(forms.ModelForm): + + class Meta: + model = EvaluationrequestModel + fields = "__all__" diff --git a/core/apps/evaluation/migrations/0018_evaluationrequestmodel.py b/core/apps/evaluation/migrations/0018_evaluationrequestmodel.py new file mode 100644 index 0000000..db85a8e --- /dev/null +++ b/core/apps/evaluation/migrations/0018_evaluationrequestmodel.py @@ -0,0 +1,45 @@ +# Generated by Django 5.2.7 on 2026-03-10 08:34 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('evaluation', '0017_autoevaluationmodel_car_brand_and_more'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='EvaluationrequestModel', + 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)), + ('rate_type', models.CharField(choices=[('auto', 'Automobil'), ('real_estate', "Ko'chmas mulk"), ('equipment', 'Uskuna')], max_length=50, verbose_name='rate type')), + ('object_type', models.CharField(blank=True, choices=[('lightweight_auto', 'Yengil automobil'), ('truck_car', 'Yuk automobil'), ('special_tech', 'Maxsus texnika')], max_length=50, null=True, verbose_name='object type')), + ('customer_inn_number', models.CharField(max_length=20, verbose_name='customer INN number')), + ('owner_inn_number', models.CharField(max_length=20, verbose_name='owner INN number')), + ('tex_passport', models.CharField(blank=True, max_length=20, null=True, verbose_name='tex passport')), + ('value_determined', models.CharField(max_length=100, verbose_name='value determined')), + ('rate_goal', models.CharField(max_length=100, verbose_name='rate goal')), + ('property_rights', models.CharField(max_length=100, verbose_name='property rights')), + ('form_ownership', models.CharField(max_length=100, verbose_name='form ownership')), + ('worked_hours', models.IntegerField(blank=True, null=True, verbose_name='worked hours')), + ('chassi', models.IntegerField(blank=True, null=True, verbose_name='chassi')), + ('need_delivering', models.BooleanField(default=True, verbose_name='need delivering')), + ('location_lat', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True, verbose_name='location latitude')), + ('location_lng', models.DecimalField(blank=True, decimal_places=6, max_digits=9, null=True, verbose_name='location longitude')), + ('status', models.CharField(choices=[('pending', 'Kutilmoqda'), ('in_progress', 'Jarayonda'), ('completed', 'Bajarildi'), ('rejected', 'Rad etildi')], default='pending', max_length=50, verbose_name='status')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='evaluation_requests', to=settings.AUTH_USER_MODEL, verbose_name='user')), + ], + options={ + 'verbose_name': 'Evaluation Request', + 'verbose_name_plural': 'Evaluation Requests', + 'db_table': 'EvaluationRequest', + }, + ), + ] diff --git a/core/apps/evaluation/models/__init__.py b/core/apps/evaluation/models/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/models/__init__.py +++ b/core/apps/evaluation/models/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/models/request.py b/core/apps/evaluation/models/request.py new file mode 100644 index 0000000..711f8d1 --- /dev/null +++ b/core/apps/evaluation/models/request.py @@ -0,0 +1,119 @@ +from django.conf import settings +from django.db import models +from django.utils.translation import gettext_lazy as _ +from django_core.models import AbstractBaseModel +from model_bakery import baker + +from core.apps.evaluation.choices.request import ( + EvaluationRateType, + RequestObjectType, + RequestStatus, +) + + +class EvaluationrequestModel(AbstractBaseModel): + user = models.ForeignKey( + "accounts.User", + on_delete=models.CASCADE, + related_name="evaluation_requests", + verbose_name=_("user"), + ) + rate_type = models.CharField( + verbose_name=_("rate type"), + max_length=50, + choices=EvaluationRateType.choices, + ) + object_type = models.CharField( + verbose_name=_("object type"), + max_length=50, + choices=RequestObjectType.choices, + blank=True, + null=True, + ) + customer_inn_number = models.CharField( + verbose_name=_("customer INN number"), + max_length=20, + ) + owner_inn_number = models.CharField( + verbose_name=_("owner INN number"), + max_length=20, + ) + tex_passport = models.CharField( + verbose_name=_("tex passport"), + max_length=20, + blank=True, + null=True, + ) + value_determined = models.CharField( + verbose_name=_("value determined"), + max_length=100, + ) + rate_goal = models.CharField( + verbose_name=_("rate goal"), + max_length=100, + ) + property_rights = models.CharField( + verbose_name=_("property rights"), + max_length=100, + ) + form_ownership = models.CharField( + verbose_name=_("form ownership"), + max_length=100, + ) + worked_hours = models.IntegerField( + verbose_name=_("worked hours"), + blank=True, + null=True, + ) + chassi = models.IntegerField( + verbose_name=_("chassi"), + blank=True, + null=True, + ) + need_delivering = models.BooleanField( + verbose_name=_("need delivering"), + default=True, + ) + location_lat = models.DecimalField( + verbose_name=_("location latitude"), + max_digits=9, + decimal_places=6, + blank=True, + null=True, + ) + location_lng = models.DecimalField( + verbose_name=_("location longitude"), + max_digits=9, + decimal_places=6, + blank=True, + null=True, + ) + status = models.CharField( + verbose_name=_("status"), + max_length=50, + choices=RequestStatus.choices, + default=RequestStatus.PENDING, + ) + + def __str__(self): + return f"Request #{self.pk} — {self.get_rate_type_display()}" + + @classmethod + def _baker(cls): + user = baker.make(settings.AUTH_USER_MODEL) + return baker.make( + cls, + user=user, + rate_type=EvaluationRateType.AUTO, + customer_inn_number="123456789", + owner_inn_number="987654321", + value_determined="Bozor qiymati", + rate_goal="Kredit uchun", + property_rights="Xususiy", + form_ownership="Xususiy", + ) + + class Meta: + db_table = "EvaluationRequest" + verbose_name = _("Evaluation Request") + verbose_name_plural = _("Evaluation Requests") diff --git a/core/apps/evaluation/permissions/__init__.py b/core/apps/evaluation/permissions/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/permissions/__init__.py +++ b/core/apps/evaluation/permissions/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/permissions/request.py b/core/apps/evaluation/permissions/request.py new file mode 100644 index 0000000..77d376a --- /dev/null +++ b/core/apps/evaluation/permissions/request.py @@ -0,0 +1,12 @@ +from rest_framework import permissions + + +class EvaluationrequestPermission(permissions.BasePermission): + + def __init__(self) -> None: ... + + def __call__(self, *args, **kwargs): + return self + + def has_permission(self, request, view): + return True diff --git a/core/apps/evaluation/serializers/__init__.py b/core/apps/evaluation/serializers/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/serializers/__init__.py +++ b/core/apps/evaluation/serializers/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/serializers/request/EvaluationRequest.py b/core/apps/evaluation/serializers/request/EvaluationRequest.py new file mode 100644 index 0000000..7564412 --- /dev/null +++ b/core/apps/evaluation/serializers/request/EvaluationRequest.py @@ -0,0 +1,132 @@ +import re + +from rest_framework import serializers + +from core.apps.evaluation.models import EvaluationrequestModel + + +class BaseEvaluationrequestSerializer(serializers.ModelSerializer): + rate_type_display = serializers.CharField( + source="get_rate_type_display", read_only=True + ) + object_type_display = serializers.CharField( + source="get_object_type_display", read_only=True, default=None + ) + status_display = serializers.CharField( + source="get_status_display", read_only=True + ) + location = serializers.SerializerMethodField() + + class Meta: + model = EvaluationrequestModel + fields = [ + "id", + "rate_type", + "rate_type_display", + "object_type", + "object_type_display", + "customer_inn_number", + "owner_inn_number", + "tex_passport", + "value_determined", + "rate_goal", + "property_rights", + "form_ownership", + "worked_hours", + "chassi", + "need_delivering", + "location", + "status", + "status_display", + "created_at", + "updated_at", + ] + + def get_location(self, obj): + if obj.location_lat is not None and obj.location_lng is not None: + return {"lat": float(obj.location_lat), "lng": float(obj.location_lng)} + return None + + +class ListEvaluationrequestSerializer(BaseEvaluationrequestSerializer): + class Meta(BaseEvaluationrequestSerializer.Meta): + pass + + +class RetrieveEvaluationrequestSerializer(BaseEvaluationrequestSerializer): + class Meta(BaseEvaluationrequestSerializer.Meta): + pass + + +class CreateEvaluationrequestSerializer(serializers.ModelSerializer): + location = serializers.DictField( + child=serializers.FloatField(), required=False + ) + + class Meta: + model = EvaluationrequestModel + fields = [ + "rate_type", + "object_type", + "customer_inn_number", + "owner_inn_number", + "tex_passport", + "value_determined", + "rate_goal", + "property_rights", + "form_ownership", + "worked_hours", + "chassi", + "need_delivering", + "location", + ] + + def validate_tex_passport(self, value): + if value and not re.match(r"^[A-Z]{2}\s?\d{7}$", value): + raise serializers.ValidationError( + "Format: AA 1234567 (2 harf + 7 raqam)" + ) + return value + + def validate(self, attrs): + rate_type = attrs.get("rate_type") + object_type = attrs.get("object_type") + + # object_type majburiy agar rate_type=auto + if rate_type == "auto" and not object_type: + raise serializers.ValidationError( + {"object_type": "rate_type 'auto' bo'lganda object_type majburiy."} + ) + + # tex_passport majburiy agar rate_type=auto + if rate_type == "auto" and not attrs.get("tex_passport"): + raise serializers.ValidationError( + {"tex_passport": "rate_type 'auto' bo'lganda tex_passport majburiy."} + ) + + # worked_hours va chassi majburiy agar object_type=truck_car + if object_type == "truck_car": + if attrs.get("worked_hours") is None: + raise serializers.ValidationError( + {"worked_hours": "Yuk automobil uchun ishlagan soati majburiy."} + ) + if attrs.get("chassi") is None: + raise serializers.ValidationError( + {"chassi": "Yuk automobil uchun shassi majburiy."} + ) + + # location majburiy agar need_delivering=true + if attrs.get("need_delivering", True) and not attrs.get("location"): + raise serializers.ValidationError( + {"location": "Yetkazish kerak bo'lganda manzil majburiy."} + ) + + return attrs + + def create(self, validated_data): + location = validated_data.pop("location", None) + if location: + validated_data["location_lat"] = location.get("lat") + validated_data["location_lng"] = location.get("lng") + validated_data["user"] = self.context["request"].user + return super().create(validated_data) diff --git a/core/apps/evaluation/serializers/request/__init__.py b/core/apps/evaluation/serializers/request/__init__.py new file mode 100644 index 0000000..5b7d40b --- /dev/null +++ b/core/apps/evaluation/serializers/request/__init__.py @@ -0,0 +1 @@ +from .EvaluationRequest import * # noqa diff --git a/core/apps/evaluation/signals/__init__.py b/core/apps/evaluation/signals/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/signals/__init__.py +++ b/core/apps/evaluation/signals/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/signals/request.py b/core/apps/evaluation/signals/request.py new file mode 100644 index 0000000..332805d --- /dev/null +++ b/core/apps/evaluation/signals/request.py @@ -0,0 +1,27 @@ +from django.db.models.signals import pre_save +from django.dispatch import receiver + +from core.apps.evaluation.choices.request import RequestStatus +from core.apps.evaluation.models import EvaluationrequestModel + + +@receiver(pre_save, sender=EvaluationrequestModel) +def create_evaluation_on_approve(sender, instance, **kwargs): + if not instance.pk: + return + + try: + old = EvaluationrequestModel.objects.get(pk=instance.pk) + except EvaluationrequestModel.DoesNotExist: + return + + if old.status != RequestStatus.COMPLETED and instance.status == RequestStatus.COMPLETED: + from core.apps.evaluation.models import AutoEvaluationModel + + if instance.rate_type == "auto" and not hasattr(instance, "_evaluation_created"): + AutoEvaluationModel.objects.create( + object_type=instance.object_type or "", + tex_passport_serie_num=instance.tex_passport or "", + rating_goal=instance.rate_goal or "", + ) + instance._evaluation_created = True diff --git a/core/apps/evaluation/tests/__init__.py b/core/apps/evaluation/tests/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/tests/__init__.py +++ b/core/apps/evaluation/tests/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/tests/request/__init__.py b/core/apps/evaluation/tests/request/__init__.py new file mode 100644 index 0000000..375943d --- /dev/null +++ b/core/apps/evaluation/tests/request/__init__.py @@ -0,0 +1 @@ +from .test_EvaluationRequest import * # noqa diff --git a/core/apps/evaluation/tests/request/test_EvaluationRequest.py b/core/apps/evaluation/tests/request/test_EvaluationRequest.py new file mode 100644 index 0000000..6e1f928 --- /dev/null +++ b/core/apps/evaluation/tests/request/test_EvaluationRequest.py @@ -0,0 +1,101 @@ +import pytest +from django.urls import reverse +from rest_framework.test import APIClient + +from core.apps.evaluation.models import EvaluationrequestModel + + +@pytest.fixture +def instance(db): + return EvaluationrequestModel._baker() + + +@pytest.fixture +def api_client(instance): + client = APIClient() + client.force_authenticate(user=instance.user) + return client, instance + + +@pytest.fixture +def data(api_client): + client, instance = api_client + return ( + { + "list": reverse("evaluation-request-list"), + "retrieve": reverse("evaluation-request-detail", kwargs={"pk": instance.pk}), + "retrieve-not-found": reverse("evaluation-request-detail", kwargs={"pk": 1000}), + }, + client, + instance, + ) + + +@pytest.mark.django_db +def test_list(data): + urls, client, _ = data + response = client.get(urls["list"]) + data_resp = response.json() + assert response.status_code == 200 + assert data_resp["status"] is True + + +@pytest.mark.django_db +def test_retrieve(data): + urls, client, _ = data + response = client.get(urls["retrieve"]) + data_resp = response.json() + assert response.status_code == 200 + assert data_resp["status"] is True + + +@pytest.mark.django_db +def test_retrieve_not_found(data): + urls, client, _ = data + response = client.get(urls["retrieve-not-found"]) + data_resp = response.json() + assert response.status_code == 404 + assert data_resp["status"] is False + + +# @pytest.mark.django_db +# def test_create(data): +# urls, client, _ = data +# response = client.post(urls["list"], data={"name": "test"}) +# assert response.json()["status"] is True +# assert response.status_code == 201 + + +# @pytest.mark.django_db +# def test_update(data): +# urls, client, _ = data +# response = client.patch(urls["retrieve"], data={"name": "updated"}) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# +# # verify updated value +# response = client.get(urls["retrieve"]) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# assert response.json()["data"]["name"] == "updated" + + +# @pytest.mark.django_db +# def test_partial_update(): +# urls, client, _ = data +# response = client.patch(urls["retrieve"], data={"name": "updated"}) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# +# # verify updated value +# response = client.get(urls["retrieve"]) +# assert response.json()["status"] is True +# assert response.status_code == 200 +# assert response.json()["data"]["name"] == "updated" + + +# @pytest.mark.django_db +# def test_destroy(data): +# urls, client, _ = data +# response = client.delete(urls["retrieve"]) +# assert response.status_code == 204 diff --git a/core/apps/evaluation/translation/__init__.py b/core/apps/evaluation/translation/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/translation/__init__.py +++ b/core/apps/evaluation/translation/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/translation/request.py b/core/apps/evaluation/translation/request.py new file mode 100644 index 0000000..26a6047 --- /dev/null +++ b/core/apps/evaluation/translation/request.py @@ -0,0 +1,8 @@ +from modeltranslation.translator import TranslationOptions, register + +from core.apps.evaluation.models import EvaluationrequestModel + + +@register(EvaluationrequestModel) +class EvaluationrequestTranslation(TranslationOptions): + fields = [] diff --git a/core/apps/evaluation/urls.py b/core/apps/evaluation/urls.py index d31f5fb..ecdc5c2 100644 --- a/core/apps/evaluation/urls.py +++ b/core/apps/evaluation/urls.py @@ -5,6 +5,7 @@ from .views import ( AutoEvaluationView, CustomerView, EvaluationReportView, + EvaluationrequestView, MovablePropertyEvaluationView, PropertyOwnerView, QuickEvaluationView, @@ -16,6 +17,7 @@ from .views import ( ) router = DefaultRouter() +router.register("evaluation-request", EvaluationrequestView, basename="evaluation-request") router.register("reference-item", ReferenceitemView, basename="reference-item") router.register("valuation-document", ValuationDocumentView, basename="valuation-document") router.register("evaluation-report", EvaluationReportView, basename="evaluation-report") diff --git a/core/apps/evaluation/validators/__init__.py b/core/apps/evaluation/validators/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/validators/__init__.py +++ b/core/apps/evaluation/validators/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/validators/request.py b/core/apps/evaluation/validators/request.py new file mode 100644 index 0000000..c9394ad --- /dev/null +++ b/core/apps/evaluation/validators/request.py @@ -0,0 +1,8 @@ +# from django.core.exceptions import ValidationError + + +class EvaluationrequestValidator: + def __init__(self): ... + + def __call__(self): + return True diff --git a/core/apps/evaluation/views/__init__.py b/core/apps/evaluation/views/__init__.py index 9b33385..e1e2f06 100644 --- a/core/apps/evaluation/views/__init__.py +++ b/core/apps/evaluation/views/__init__.py @@ -6,5 +6,6 @@ from .quick import * # noqa from .real_estate import * # noqa from .reference import * # noqa from .report import * # noqa +from .request import * # noqa from .valuation import * # noqa from .vehicle import * # noqa diff --git a/core/apps/evaluation/views/request.py b/core/apps/evaluation/views/request.py new file mode 100644 index 0000000..338efed --- /dev/null +++ b/core/apps/evaluation/views/request.py @@ -0,0 +1,56 @@ +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.pagination import PageNumberPagination +from rest_framework.permissions import AllowAny, IsAuthenticated +from rest_framework.viewsets import ModelViewSet + +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, +) + + +# class RequestPagination(PageNumberPagination): +# page_size = 20 +# page_size_query_param = "limit" +# max_page_size = 100 + + +@extend_schema(tags=["EvaluationRequest"]) +class EvaluationrequestView(BaseViewSetMixin, ModelViewSet): + serializer_class = ListEvaluationrequestSerializer + permission_classes = [IsAuthenticated] + # pagination_class = RequestPagination + + filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter] + filterset_class = EvaluationrequestFilter + search_fields = [ + "customer_inn_number", + "owner_inn_number", + "tex_passport", + ] + ordering_fields = [ + "created_at", + "updated_at", + "rate_type", + "object_type", + "status", + ] + ordering = ["-created_at"] + + action_permission_classes = {} + action_serializer_class = { + "list": ListEvaluationrequestSerializer, + "retrieve": RetrieveEvaluationrequestSerializer, + "create": CreateEvaluationrequestSerializer, + } + + def get_queryset(self): + return EvaluationrequestModel.objects.filter( + user=self.request.user + ).order_by("-created_at")