Merge pull request 'feat: add ReferenceItem model and update QuickEvaluation FKs' (#23) from feat/quick-evaluation-create-api into main
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 1m24s
Some checks failed
Deploy to Production / build-and-deploy (push) Failing after 1m24s
Reviewed-on: #23
This commit is contained in:
@@ -107,4 +107,15 @@ PAGES = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"title": _("Ma'lumotnomalari"),
|
||||||
|
"separator": True,
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"title": _("Ma'lumotnomalar"),
|
||||||
|
"icon": "category",
|
||||||
|
"link": reverse_lazy("admin:evaluation_referenceitemmodel_changelist"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
@@ -10,10 +10,9 @@ class QuickEvaluationAdmin(ModelAdmin):
|
|||||||
"id",
|
"id",
|
||||||
"created_by",
|
"created_by",
|
||||||
"brand",
|
"brand",
|
||||||
"model",
|
"marka",
|
||||||
"license_plate",
|
"car_number",
|
||||||
"manufacture_year",
|
"car_manufactured_date",
|
||||||
"condition",
|
|
||||||
"estimated_price",
|
"estimated_price",
|
||||||
"status",
|
"status",
|
||||||
"car_type",
|
"car_type",
|
||||||
@@ -21,20 +20,14 @@ class QuickEvaluationAdmin(ModelAdmin):
|
|||||||
"created_at",
|
"created_at",
|
||||||
)
|
)
|
||||||
list_filter = (
|
list_filter = (
|
||||||
"fuel_type",
|
|
||||||
"body_type",
|
|
||||||
"condition",
|
|
||||||
"status",
|
"status",
|
||||||
"car_type",
|
"car_type",
|
||||||
"state_car",
|
|
||||||
)
|
)
|
||||||
search_fields = (
|
search_fields = (
|
||||||
"brand",
|
"car_number",
|
||||||
"model",
|
|
||||||
"license_plate",
|
|
||||||
"vin_number",
|
"vin_number",
|
||||||
"engine_number",
|
"engine_number",
|
||||||
"tech_passport_number",
|
"tex_passport_serie_num",
|
||||||
)
|
)
|
||||||
readonly_fields = ("created_at", "updated_at")
|
readonly_fields = ("created_at", "updated_at")
|
||||||
autocomplete_fields = ("created_by",)
|
autocomplete_fields = ("created_by",)
|
||||||
@@ -42,20 +35,25 @@ class QuickEvaluationAdmin(ModelAdmin):
|
|||||||
("Foydalanuvchi", {
|
("Foydalanuvchi", {
|
||||||
"fields": ("created_by",),
|
"fields": ("created_by",),
|
||||||
}),
|
}),
|
||||||
|
("Tex passport", {
|
||||||
|
"fields": (
|
||||||
|
"tex_passport_serie_num",
|
||||||
|
("tech_passport_issued_date", "tech_passport_issued_place"),
|
||||||
|
"tex_passport_file",
|
||||||
|
),
|
||||||
|
}),
|
||||||
("Transport ma'lumotlari", {
|
("Transport ma'lumotlari", {
|
||||||
"fields": (
|
"fields": (
|
||||||
"tech_passport_number",
|
"car_number",
|
||||||
"license_plate",
|
("brand", "marka"),
|
||||||
("brand", "model"),
|
("car_manufactured_date", "color"),
|
||||||
("manufacture_year", "color"),
|
|
||||||
("vin_number", "engine_number"),
|
("vin_number", "engine_number"),
|
||||||
"mileage",
|
("distance_covered", "car_position"),
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
("Texnik holat", {
|
("Texnik holat", {
|
||||||
"fields": (
|
"fields": (
|
||||||
("fuel_type", "body_type"),
|
("fuel_type", "body_type"),
|
||||||
"condition",
|
|
||||||
("car_type", "state_car"),
|
("car_type", "state_car"),
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
|
|||||||
18
core/apps/evaluation/admin/reference.py
Normal file
18
core/apps/evaluation/admin/reference.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from django.contrib import admin
|
||||||
|
from unfold.admin import ModelAdmin
|
||||||
|
|
||||||
|
from core.apps.evaluation.models import ReferenceitemModel
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(ReferenceitemModel)
|
||||||
|
class ReferenceitemAdmin(ModelAdmin):
|
||||||
|
list_display = ("id", "type", "name", "parent", "order", "is_active")
|
||||||
|
list_filter = ("type", "is_active")
|
||||||
|
search_fields = ("name",)
|
||||||
|
list_editable = ("order", "is_active")
|
||||||
|
autocomplete_fields = ("parent",)
|
||||||
|
fieldsets = (
|
||||||
|
(None, {
|
||||||
|
"fields": ("type", "name", "parent", "order", "is_active"),
|
||||||
|
}),
|
||||||
|
)
|
||||||
@@ -15,9 +15,3 @@ class CarType(models.TextChoices):
|
|||||||
TRUCK = "truck", _("Truck")
|
TRUCK = "truck", _("Truck")
|
||||||
BUS = "bus", _("Bus")
|
BUS = "bus", _("Bus")
|
||||||
MOTO = "moto", _("Moto")
|
MOTO = "moto", _("Moto")
|
||||||
|
|
||||||
|
|
||||||
class CarState(models.TextChoices):
|
|
||||||
GOOD = "good", _("Good")
|
|
||||||
SATISFACTORY = "satisfactory", _("Satisfactory")
|
|
||||||
BAD = "bad", _("Bad")
|
|
||||||
|
|||||||
12
core/apps/evaluation/choices/reference.py
Normal file
12
core/apps/evaluation/choices/reference.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class ReferenceType(models.TextChoices):
|
||||||
|
BRAND = "brand", _("Brand")
|
||||||
|
MARKA = "marka", _("Marka")
|
||||||
|
COLOR = "color", _("Color")
|
||||||
|
FUEL_TYPE = "fuel_type", _("Fuel type")
|
||||||
|
BODY_TYPE = "body_type", _("Body type")
|
||||||
|
CAR_POSITION = "car_position", _("Car position")
|
||||||
|
STATE_CAR = "state_car", _("Car state")
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
@@ -6,11 +6,11 @@ from core.apps.evaluation.models import QuickEvaluationModel
|
|||||||
class QuickevaluationFilter(filters.FilterSet):
|
class QuickevaluationFilter(filters.FilterSet):
|
||||||
status = filters.CharFilter(method="filter_status")
|
status = filters.CharFilter(method="filter_status")
|
||||||
car_type = filters.CharFilter(field_name="car_type", lookup_expr="exact")
|
car_type = filters.CharFilter(field_name="car_type", lookup_expr="exact")
|
||||||
state_car = filters.CharFilter(field_name="state_car", lookup_expr="exact")
|
state_car = filters.NumberFilter(field_name="state_car", lookup_expr="exact")
|
||||||
created_from = filters.DateFilter(field_name="created_at", lookup_expr="gte")
|
created_from = filters.DateFilter(field_name="created_at", lookup_expr="gte")
|
||||||
created_to = filters.DateFilter(field_name="created_at", lookup_expr="lte")
|
created_to = filters.DateFilter(field_name="created_at", lookup_expr="lte")
|
||||||
year_from = filters.NumberFilter(field_name="manufacture_year", lookup_expr="gte")
|
year_from = filters.NumberFilter(field_name="car_manufactured_date", lookup_expr="gte")
|
||||||
year_to = filters.NumberFilter(field_name="manufacture_year", lookup_expr="lte")
|
year_to = filters.NumberFilter(field_name="car_manufactured_date", lookup_expr="lte")
|
||||||
|
|
||||||
def filter_status(self, queryset, name, value):
|
def filter_status(self, queryset, name, value):
|
||||||
if value:
|
if value:
|
||||||
|
|||||||
17
core/apps/evaluation/filters/reference.py
Normal file
17
core/apps/evaluation/filters/reference.py
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
from django_filters import rest_framework as filters
|
||||||
|
|
||||||
|
from core.apps.evaluation.models import ReferenceitemModel
|
||||||
|
|
||||||
|
|
||||||
|
class ReferenceitemFilter(filters.FilterSet):
|
||||||
|
type = filters.CharFilter(field_name="type", lookup_expr="exact")
|
||||||
|
parent = filters.NumberFilter(field_name="parent", lookup_expr="exact")
|
||||||
|
is_active = filters.BooleanFilter(field_name="is_active")
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ReferenceitemModel
|
||||||
|
fields = [
|
||||||
|
"type",
|
||||||
|
"parent",
|
||||||
|
"is_active",
|
||||||
|
]
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
10
core/apps/evaluation/forms/reference.py
Normal file
10
core/apps/evaluation/forms/reference.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from django import forms
|
||||||
|
|
||||||
|
from core.apps.evaluation.models import ReferenceitemModel
|
||||||
|
|
||||||
|
|
||||||
|
class ReferenceitemForm(forms.ModelForm):
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ReferenceitemModel
|
||||||
|
fields = "__all__"
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2026-03-09 09:57
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('evaluation', '0011_update_choices_to_english'),
|
||||||
|
('shared', '0002_settingsmodel_created_at_settingsmodel_description_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='condition',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='license_plate',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='manufacture_year',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='mileage',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='model',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='tech_passport_number',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='car_manufactured_date',
|
||||||
|
field=models.IntegerField(blank=True, null=True, verbose_name='manufacture year'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='car_number',
|
||||||
|
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='car number'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='car_position',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_positions', to='shared.optionsmodel', verbose_name='car position'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='distance_covered',
|
||||||
|
field=models.IntegerField(blank=True, null=True, verbose_name='distance covered (km)'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='marka',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_markas', to='shared.optionsmodel', verbose_name='marka'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='tech_passport_issued_date',
|
||||||
|
field=models.DateField(blank=True, null=True, verbose_name='tech passport issued date'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='tech_passport_issued_place',
|
||||||
|
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='tech passport issued place'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='tex_passport_file',
|
||||||
|
field=models.FileField(blank=True, null=True, upload_to='quick_evaluation/tech_passports/%Y/%m/', verbose_name='tech passport file'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='tex_passport_serie_num',
|
||||||
|
field=models.CharField(blank=True, max_length=20, null=True, verbose_name='tech passport series and number'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='body_type',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_body_types', to='shared.optionsmodel', verbose_name='body type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='brand',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_brands', to='shared.optionsmodel', verbose_name='brand'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='color',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_colors', to='shared.optionsmodel', verbose_name='color'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='fuel_type',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_fuel_types', to='shared.optionsmodel', verbose_name='fuel type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='state_car',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_states', to='shared.optionsmodel', verbose_name='car state'),
|
||||||
|
),
|
||||||
|
]
|
||||||
33
core/apps/evaluation/migrations/0013_referenceitemmodel.py
Normal file
33
core/apps/evaluation/migrations/0013_referenceitemmodel.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2026-03-09 10:49
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('evaluation', '0012_remove_quickevaluationmodel_condition_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ReferenceitemModel',
|
||||||
|
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)),
|
||||||
|
('type', models.CharField(choices=[('brand', 'Brand'), ('marka', 'Marka'), ('color', 'Color'), ('fuel_type', 'Fuel type'), ('body_type', 'Body type'), ('car_position', 'Car position'), ('state_car', 'Car state')], max_length=50, verbose_name='type')),
|
||||||
|
('name', models.CharField(max_length=255, verbose_name='name')),
|
||||||
|
('order', models.IntegerField(default=0, verbose_name='order')),
|
||||||
|
('is_active', models.BooleanField(default=True, verbose_name='is active')),
|
||||||
|
('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='evaluation.referenceitemmodel', verbose_name='parent')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Reference Item',
|
||||||
|
'verbose_name_plural': 'Reference Items',
|
||||||
|
'db_table': 'ReferenceItem',
|
||||||
|
'ordering': ['type', 'order', 'name'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2026-03-09 10:51
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('evaluation', '0013_referenceitemmodel'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='body_type',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_body_types', to='evaluation.referenceitemmodel', verbose_name='body type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='brand',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_brands', to='evaluation.referenceitemmodel', verbose_name='brand'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='car_position',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_positions', to='evaluation.referenceitemmodel', verbose_name='car position'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='color',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_colors', to='evaluation.referenceitemmodel', verbose_name='color'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='fuel_type',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_fuel_types', to='evaluation.referenceitemmodel', verbose_name='fuel type'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='marka',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_markas', to='evaluation.referenceitemmodel', verbose_name='marka'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='quickevaluationmodel',
|
||||||
|
name='state_car',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='quick_eval_states', to='evaluation.referenceitemmodel', verbose_name='car state'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from django_core.models import AbstractBaseModel
|
from django_core.models import AbstractBaseModel
|
||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
|
|
||||||
from core.apps.evaluation.choices.quick import CarState, CarType, QuickEvaluationStatus
|
from core.apps.evaluation.choices.quick import CarType, QuickEvaluationStatus
|
||||||
from core.apps.evaluation.choices.vehicle import BodyType, FuelType, VehicleCondition
|
|
||||||
|
|
||||||
|
|
||||||
class QuickEvaluationModel(AbstractBaseModel):
|
class QuickEvaluationModel(AbstractBaseModel):
|
||||||
@@ -16,46 +15,115 @@ class QuickEvaluationModel(AbstractBaseModel):
|
|||||||
related_name="quick_evaluations",
|
related_name="quick_evaluations",
|
||||||
verbose_name=_("created by"),
|
verbose_name=_("created by"),
|
||||||
)
|
)
|
||||||
tech_passport_number = models.CharField(
|
|
||||||
verbose_name=_("tech passport number"), max_length=50, blank=True, null=True
|
# Tex passport
|
||||||
|
tex_passport_serie_num = models.CharField(
|
||||||
|
verbose_name=_("tech passport series and number"),
|
||||||
|
max_length=20,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
license_plate = models.CharField(
|
tech_passport_issued_date = models.DateField(
|
||||||
verbose_name=_("license plate"), max_length=20, blank=True, null=True
|
verbose_name=_("tech passport issued date"),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
)
|
)
|
||||||
model = models.CharField(verbose_name=_("model"), max_length=255, blank=True, null=True)
|
tech_passport_issued_place = models.CharField(
|
||||||
brand = models.CharField(verbose_name=_("brand"), max_length=255, blank=True, null=True)
|
verbose_name=_("tech passport issued place"),
|
||||||
manufacture_year = models.IntegerField(
|
max_length=255,
|
||||||
verbose_name=_("manufacture year"), blank=True, null=True
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
tex_passport_file = models.FileField(
|
||||||
|
verbose_name=_("tech passport file"),
|
||||||
|
upload_to="quick_evaluation/tech_passports/%Y/%m/",
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Car info
|
||||||
|
car_type = models.CharField(
|
||||||
|
verbose_name=_("car type"),
|
||||||
|
max_length=50,
|
||||||
|
choices=CarType.choices,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
brand = models.ForeignKey(
|
||||||
|
"evaluation.ReferenceitemModel",
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="quick_eval_brands",
|
||||||
|
verbose_name=_("brand"),
|
||||||
|
)
|
||||||
|
marka = models.ForeignKey(
|
||||||
|
"evaluation.ReferenceitemModel",
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="quick_eval_markas",
|
||||||
|
verbose_name=_("marka"),
|
||||||
|
)
|
||||||
|
car_position = models.ForeignKey(
|
||||||
|
"evaluation.ReferenceitemModel",
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="quick_eval_positions",
|
||||||
|
verbose_name=_("car position"),
|
||||||
|
)
|
||||||
|
distance_covered = models.IntegerField(
|
||||||
|
verbose_name=_("distance covered (km)"),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
body_type = models.ForeignKey(
|
||||||
|
"evaluation.ReferenceitemModel",
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="quick_eval_body_types",
|
||||||
|
verbose_name=_("body type"),
|
||||||
)
|
)
|
||||||
mileage = models.IntegerField(verbose_name=_("mileage"), blank=True, null=True)
|
|
||||||
vin_number = models.CharField(
|
vin_number = models.CharField(
|
||||||
verbose_name=_("VIN number"), max_length=50, blank=True, null=True
|
verbose_name=_("VIN number"), max_length=50, blank=True, null=True
|
||||||
)
|
)
|
||||||
|
car_number = models.CharField(
|
||||||
|
verbose_name=_("car number"), max_length=20, blank=True, null=True
|
||||||
|
)
|
||||||
|
car_manufactured_date = models.IntegerField(
|
||||||
|
verbose_name=_("manufacture year"), blank=True, null=True
|
||||||
|
)
|
||||||
engine_number = models.CharField(
|
engine_number = models.CharField(
|
||||||
verbose_name=_("engine number"), max_length=50, blank=True, null=True
|
verbose_name=_("engine number"), max_length=50, blank=True, null=True
|
||||||
)
|
)
|
||||||
color = models.CharField(verbose_name=_("color"), max_length=50, blank=True, null=True)
|
color = models.ForeignKey(
|
||||||
fuel_type = models.CharField(
|
"evaluation.ReferenceitemModel",
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="quick_eval_colors",
|
||||||
|
verbose_name=_("color"),
|
||||||
|
)
|
||||||
|
fuel_type = models.ForeignKey(
|
||||||
|
"evaluation.ReferenceitemModel",
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="quick_eval_fuel_types",
|
||||||
verbose_name=_("fuel type"),
|
verbose_name=_("fuel type"),
|
||||||
max_length=50,
|
|
||||||
choices=FuelType.choices,
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
)
|
)
|
||||||
body_type = models.CharField(
|
state_car = models.ForeignKey(
|
||||||
verbose_name=_("body type"),
|
"evaluation.ReferenceitemModel",
|
||||||
max_length=50,
|
on_delete=models.SET_NULL,
|
||||||
choices=BodyType.choices,
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
null=True,
|
||||||
)
|
|
||||||
condition = models.CharField(
|
|
||||||
verbose_name=_("condition"),
|
|
||||||
max_length=50,
|
|
||||||
choices=VehicleCondition.choices,
|
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
related_name="quick_eval_states",
|
||||||
|
verbose_name=_("car state"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Result
|
||||||
estimated_price = models.DecimalField(
|
estimated_price = models.DecimalField(
|
||||||
verbose_name=_("estimated price"),
|
verbose_name=_("estimated price"),
|
||||||
max_digits=15,
|
max_digits=15,
|
||||||
@@ -69,20 +137,6 @@ class QuickEvaluationModel(AbstractBaseModel):
|
|||||||
choices=QuickEvaluationStatus.choices,
|
choices=QuickEvaluationStatus.choices,
|
||||||
default=QuickEvaluationStatus.CREATED,
|
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):
|
def __str__(self):
|
||||||
return f"Quick Evaluation {self.pk} by {self.created_by}"
|
return f"Quick Evaluation {self.pk} by {self.created_by}"
|
||||||
|
|||||||
38
core/apps/evaluation/models/reference.py
Normal file
38
core/apps/evaluation/models/reference.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
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.reference import ReferenceType
|
||||||
|
|
||||||
|
|
||||||
|
class ReferenceitemModel(AbstractBaseModel):
|
||||||
|
type = models.CharField(
|
||||||
|
verbose_name=_("type"),
|
||||||
|
max_length=50,
|
||||||
|
choices=ReferenceType.choices,
|
||||||
|
)
|
||||||
|
name = models.CharField(verbose_name=_("name"), max_length=255)
|
||||||
|
parent = models.ForeignKey(
|
||||||
|
"self",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
null=True,
|
||||||
|
blank=True,
|
||||||
|
related_name="children",
|
||||||
|
verbose_name=_("parent"),
|
||||||
|
)
|
||||||
|
order = models.IntegerField(verbose_name=_("order"), default=0)
|
||||||
|
is_active = models.BooleanField(verbose_name=_("is active"), default=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.get_type_display()}: {self.name}"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _baker(cls):
|
||||||
|
return baker.make(cls)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = "ReferenceItem"
|
||||||
|
verbose_name = _("Reference Item")
|
||||||
|
verbose_name_plural = _("Reference Items")
|
||||||
|
ordering = ["type", "order", "name"]
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
12
core/apps/evaluation/permissions/reference.py
Normal file
12
core/apps/evaluation/permissions/reference.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from rest_framework import permissions
|
||||||
|
|
||||||
|
|
||||||
|
class ReferenceitemPermission(permissions.BasePermission):
|
||||||
|
|
||||||
|
def __init__(self) -> None: ...
|
||||||
|
|
||||||
|
def __call__(self, *args, **kwargs):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
return True
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
@@ -1,14 +1,21 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from core.apps.evaluation.models import QuickEvaluationModel
|
from core.apps.evaluation.models import QuickEvaluationModel
|
||||||
|
|
||||||
|
|
||||||
class BaseQuickevaluationSerializer(serializers.ModelSerializer):
|
class BaseQuickevaluationSerializer(serializers.ModelSerializer):
|
||||||
fuel_type_display = serializers.CharField(source="get_fuel_type_display", read_only=True)
|
|
||||||
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)
|
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)
|
status_display = serializers.CharField(source="get_status_display", read_only=True)
|
||||||
car_type_display = serializers.CharField(source="get_car_type_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)
|
brand_name = serializers.CharField(source="brand.name", read_only=True, default=None)
|
||||||
|
marka_name = serializers.CharField(source="marka.name", read_only=True, default=None)
|
||||||
|
color_name = serializers.CharField(source="color.name", read_only=True, default=None)
|
||||||
|
fuel_type_name = serializers.CharField(source="fuel_type.name", read_only=True, default=None)
|
||||||
|
body_type_name = serializers.CharField(source="body_type.name", read_only=True, default=None)
|
||||||
|
state_car_name = serializers.CharField(source="state_car.name", read_only=True, default=None)
|
||||||
|
car_position_name = serializers.CharField(source="car_position.name", read_only=True, default=None)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = QuickEvaluationModel
|
model = QuickEvaluationModel
|
||||||
@@ -17,55 +24,104 @@ class BaseQuickevaluationSerializer(serializers.ModelSerializer):
|
|||||||
"created_by",
|
"created_by",
|
||||||
"created_by_name",
|
"created_by_name",
|
||||||
"brand",
|
"brand",
|
||||||
"model",
|
"brand_name",
|
||||||
"license_plate",
|
"marka",
|
||||||
"manufacture_year",
|
"marka_name",
|
||||||
|
"car_number",
|
||||||
|
"car_manufactured_date",
|
||||||
"estimated_price",
|
"estimated_price",
|
||||||
"status",
|
"status",
|
||||||
"status_display",
|
"status_display",
|
||||||
"car_type",
|
"car_type",
|
||||||
"car_type_display",
|
"car_type_display",
|
||||||
"state_car",
|
"state_car",
|
||||||
"state_car_display",
|
"state_car_name",
|
||||||
"created_at",
|
"created_at",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class ListQuickevaluationSerializer(BaseQuickevaluationSerializer):
|
class ListQuickevaluationSerializer(BaseQuickevaluationSerializer):
|
||||||
class Meta(BaseQuickevaluationSerializer.Meta):
|
class Meta(BaseQuickevaluationSerializer.Meta):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class RetrieveQuickevaluationSerializer(BaseQuickevaluationSerializer):
|
class RetrieveQuickevaluationSerializer(BaseQuickevaluationSerializer):
|
||||||
class Meta(BaseQuickevaluationSerializer.Meta):
|
class Meta(BaseQuickevaluationSerializer.Meta):
|
||||||
fields = BaseQuickevaluationSerializer.Meta.fields + [
|
fields = BaseQuickevaluationSerializer.Meta.fields + [
|
||||||
"tech_passport_number",
|
"tex_passport_serie_num",
|
||||||
"mileage",
|
"tech_passport_issued_date",
|
||||||
|
"tech_passport_issued_place",
|
||||||
|
"tex_passport_file",
|
||||||
|
"car_position",
|
||||||
|
"car_position_name",
|
||||||
|
"distance_covered",
|
||||||
|
"body_type",
|
||||||
|
"body_type_name",
|
||||||
"vin_number",
|
"vin_number",
|
||||||
"engine_number",
|
"engine_number",
|
||||||
"color",
|
"color",
|
||||||
|
"color_name",
|
||||||
"fuel_type",
|
"fuel_type",
|
||||||
"fuel_type_display",
|
"fuel_type_name",
|
||||||
"body_type",
|
|
||||||
"body_type_display",
|
|
||||||
"condition",
|
|
||||||
"condition_display",
|
|
||||||
"updated_at",
|
"updated_at",
|
||||||
]
|
]
|
||||||
|
|
||||||
class CreateQuickevaluationSerializer(BaseQuickevaluationSerializer):
|
|
||||||
class Meta(BaseQuickevaluationSerializer.Meta):
|
class CreateQuickevaluationSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = QuickEvaluationModel
|
||||||
fields = [
|
fields = [
|
||||||
"tech_passport_number",
|
"tex_passport_serie_num",
|
||||||
"license_plate",
|
"tech_passport_issued_date",
|
||||||
"model",
|
"tech_passport_issued_place",
|
||||||
|
"tex_passport_file",
|
||||||
|
"car_type",
|
||||||
"brand",
|
"brand",
|
||||||
"manufacture_year",
|
"marka",
|
||||||
"mileage",
|
"car_position",
|
||||||
|
"distance_covered",
|
||||||
|
"body_type",
|
||||||
"vin_number",
|
"vin_number",
|
||||||
|
"car_number",
|
||||||
|
"car_manufactured_date",
|
||||||
"engine_number",
|
"engine_number",
|
||||||
"color",
|
"color",
|
||||||
"fuel_type",
|
"fuel_type",
|
||||||
"body_type",
|
|
||||||
"condition",
|
|
||||||
"car_type",
|
|
||||||
"state_car",
|
"state_car",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def validate_tex_passport_serie_num(self, value):
|
||||||
|
if value and not re.match(r"^[A-Z]{3}\s?\d{7}$", value):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
"Format: AAA 1234567 (3 harf + 7 raqam)"
|
||||||
|
)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def validate_vin_number(self, value):
|
||||||
|
if value and len(value) != 17:
|
||||||
|
raise serializers.ValidationError("VIN raqami 17 belgidan iborat bo'lishi kerak.")
|
||||||
|
return value
|
||||||
|
|
||||||
|
def validate(self, attrs):
|
||||||
|
car_type = attrs.get("car_type")
|
||||||
|
if car_type == "lightweight":
|
||||||
|
if not attrs.get("distance_covered"):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
{"distance_covered": "car_type 'lightweight' uchun majburiy."}
|
||||||
|
)
|
||||||
|
if not attrs.get("body_type"):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
{"body_type": "car_type 'lightweight' uchun majburiy."}
|
||||||
|
)
|
||||||
|
if car_type == "truck":
|
||||||
|
if not attrs.get("vin_number"):
|
||||||
|
raise serializers.ValidationError(
|
||||||
|
{"vin_number": "car_type 'truck' uchun majburiy."}
|
||||||
|
)
|
||||||
|
return attrs
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
request = self.context.get("request")
|
||||||
|
if request and request.user and request.user.is_authenticated:
|
||||||
|
validated_data["created_by"] = request.user
|
||||||
|
return super().create(validated_data)
|
||||||
|
|||||||
48
core/apps/evaluation/serializers/reference/ReferenceItem.py
Normal file
48
core/apps/evaluation/serializers/reference/ReferenceItem.py
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from core.apps.evaluation.models import ReferenceitemModel
|
||||||
|
|
||||||
|
|
||||||
|
class BaseReferenceitemSerializer(serializers.ModelSerializer):
|
||||||
|
type_display = serializers.CharField(source="get_type_display", read_only=True)
|
||||||
|
parent_name = serializers.CharField(source="parent.name", read_only=True, default=None)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = ReferenceitemModel
|
||||||
|
fields = [
|
||||||
|
"id",
|
||||||
|
"type",
|
||||||
|
"type_display",
|
||||||
|
"name",
|
||||||
|
"parent",
|
||||||
|
"parent_name",
|
||||||
|
"order",
|
||||||
|
"is_active",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ListReferenceitemSerializer(BaseReferenceitemSerializer):
|
||||||
|
class Meta(BaseReferenceitemSerializer.Meta):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RetrieveReferenceitemSerializer(BaseReferenceitemSerializer):
|
||||||
|
children = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta(BaseReferenceitemSerializer.Meta):
|
||||||
|
fields = BaseReferenceitemSerializer.Meta.fields + ["children"]
|
||||||
|
|
||||||
|
def get_children(self, obj):
|
||||||
|
children = obj.children.filter(is_active=True).order_by("order", "name")
|
||||||
|
return ListReferenceitemSerializer(children, many=True).data
|
||||||
|
|
||||||
|
|
||||||
|
class CreateReferenceitemSerializer(BaseReferenceitemSerializer):
|
||||||
|
class Meta(BaseReferenceitemSerializer.Meta):
|
||||||
|
fields = [
|
||||||
|
"type",
|
||||||
|
"name",
|
||||||
|
"parent",
|
||||||
|
"order",
|
||||||
|
"is_active",
|
||||||
|
]
|
||||||
1
core/apps/evaluation/serializers/reference/__init__.py
Normal file
1
core/apps/evaluation/serializers/reference/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .ReferenceItem import * # noqa
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
8
core/apps/evaluation/signals/reference.py
Normal file
8
core/apps/evaluation/signals/reference.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from django.db.models.signals import post_save
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from core.apps.evaluation.models import ReferenceitemModel
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=ReferenceitemModel)
|
||||||
|
def ReferenceitemSignal(sender, instance, created, **kwargs): ...
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
1
core/apps/evaluation/tests/reference/__init__.py
Normal file
1
core/apps/evaluation/tests/reference/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from .test_ReferenceItem import * # noqa
|
||||||
101
core/apps/evaluation/tests/reference/test_ReferenceItem.py
Normal file
101
core/apps/evaluation/tests/reference/test_ReferenceItem.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import pytest
|
||||||
|
from django.urls import reverse
|
||||||
|
from rest_framework.test import APIClient
|
||||||
|
|
||||||
|
from core.apps.evaluation.models import ReferenceitemModel
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def instance(db):
|
||||||
|
return ReferenceitemModel._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("ReferenceItem-list"),
|
||||||
|
"retrieve": reverse("ReferenceItem-detail", kwargs={"pk": instance.pk}),
|
||||||
|
"retrieve-not-found": reverse("ReferenceItem-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
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
8
core/apps/evaluation/translation/reference.py
Normal file
8
core/apps/evaluation/translation/reference.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
from modeltranslation.translator import TranslationOptions, register
|
||||||
|
|
||||||
|
from core.apps.evaluation.models import ReferenceitemModel
|
||||||
|
|
||||||
|
|
||||||
|
@register(ReferenceitemModel)
|
||||||
|
class ReferenceitemTranslation(TranslationOptions):
|
||||||
|
fields = []
|
||||||
@@ -9,12 +9,14 @@ from .views import (
|
|||||||
PropertyOwnerView,
|
PropertyOwnerView,
|
||||||
QuickEvaluationView,
|
QuickEvaluationView,
|
||||||
RealEstateEvaluationView,
|
RealEstateEvaluationView,
|
||||||
|
ReferenceitemView,
|
||||||
ValuationDocumentView,
|
ValuationDocumentView,
|
||||||
ValuationView,
|
ValuationView,
|
||||||
VehicleView,
|
VehicleView,
|
||||||
)
|
)
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
|
router.register("reference-item", ReferenceitemView, basename="reference-item")
|
||||||
router.register("valuation-document", ValuationDocumentView, basename="valuation-document")
|
router.register("valuation-document", ValuationDocumentView, basename="valuation-document")
|
||||||
router.register("evaluation-report", EvaluationReportView, basename="evaluation-report")
|
router.register("evaluation-report", EvaluationReportView, basename="evaluation-report")
|
||||||
router.register("quick-evaluation", QuickEvaluationView, basename="quick-evaluation")
|
router.register("quick-evaluation", QuickEvaluationView, basename="quick-evaluation")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
8
core/apps/evaluation/validators/reference.py
Normal file
8
core/apps/evaluation/validators/reference.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
|
class ReferenceitemValidator:
|
||||||
|
def __init__(self): ...
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
return True
|
||||||
@@ -4,6 +4,7 @@ from .document import * # noqa
|
|||||||
from .movable import * # noqa
|
from .movable import * # noqa
|
||||||
from .quick import * # noqa
|
from .quick import * # noqa
|
||||||
from .real_estate import * # noqa
|
from .real_estate import * # noqa
|
||||||
|
from .reference import * # noqa
|
||||||
from .report import * # noqa
|
from .report import * # noqa
|
||||||
from .valuation import * # noqa
|
from .valuation import * # noqa
|
||||||
from .vehicle import * # noqa
|
from .vehicle import * # noqa
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ 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.filters import OrderingFilter, SearchFilter
|
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
|
||||||
from rest_framework.viewsets import ReadOnlyModelViewSet
|
from rest_framework.viewsets import ModelViewSet
|
||||||
|
|
||||||
from core.apps.evaluation.filters.quick import QuickevaluationFilter
|
from core.apps.evaluation.filters.quick import QuickevaluationFilter
|
||||||
from core.apps.evaluation.models import QuickEvaluationModel
|
from core.apps.evaluation.models import QuickEvaluationModel
|
||||||
@@ -15,27 +16,31 @@ from core.apps.evaluation.serializers.quick import (
|
|||||||
|
|
||||||
|
|
||||||
@extend_schema(tags=["QuickEvaluation"])
|
@extend_schema(tags=["QuickEvaluation"])
|
||||||
class QuickEvaluationView(BaseViewSetMixin, ReadOnlyModelViewSet):
|
class QuickEvaluationView(BaseViewSetMixin, ModelViewSet):
|
||||||
queryset = QuickEvaluationModel.objects.select_related("created_by").all()
|
queryset = QuickEvaluationModel.objects.select_related(
|
||||||
|
"created_by", "brand", "marka", "color", "fuel_type",
|
||||||
|
"body_type", "state_car", "car_position",
|
||||||
|
).all()
|
||||||
serializer_class = ListQuickevaluationSerializer
|
serializer_class = ListQuickevaluationSerializer
|
||||||
permission_classes = [AllowAny]
|
permission_classes = [AllowAny]
|
||||||
|
parser_classes = [MultiPartParser, FormParser]
|
||||||
|
|
||||||
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
filterset_class = QuickevaluationFilter
|
filterset_class = QuickevaluationFilter
|
||||||
search_fields = ["license_plate", "model", "brand"]
|
search_fields = ["car_number", "marka__name", "brand__name"]
|
||||||
ordering_fields = [
|
ordering_fields = [
|
||||||
"created_at",
|
"created_at",
|
||||||
"updated_at",
|
"updated_at",
|
||||||
"license_plate",
|
"car_number",
|
||||||
"brand",
|
"brand__name",
|
||||||
"model",
|
"marka__name",
|
||||||
"car_type",
|
"car_type",
|
||||||
"manufacture_year",
|
"car_manufactured_date",
|
||||||
"color",
|
"color__name",
|
||||||
"fuel_type",
|
"fuel_type__name",
|
||||||
"state_car",
|
"state_car__name",
|
||||||
"status",
|
"status",
|
||||||
"mileage",
|
"distance_covered",
|
||||||
]
|
]
|
||||||
ordering = ["-created_at"]
|
ordering = ["-created_at"]
|
||||||
|
|
||||||
|
|||||||
34
core/apps/evaluation/views/reference.py
Normal file
34
core/apps/evaluation/views/reference.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
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.reference import ReferenceitemFilter
|
||||||
|
from core.apps.evaluation.models import ReferenceitemModel
|
||||||
|
from core.apps.evaluation.serializers.reference import (
|
||||||
|
CreateReferenceitemSerializer,
|
||||||
|
ListReferenceitemSerializer,
|
||||||
|
RetrieveReferenceitemSerializer,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@extend_schema(tags=["ReferenceItem"])
|
||||||
|
class ReferenceitemView(BaseViewSetMixin, ReadOnlyModelViewSet):
|
||||||
|
queryset = ReferenceitemModel.objects.select_related("parent").filter(is_active=True)
|
||||||
|
serializer_class = ListReferenceitemSerializer
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
|
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
|
||||||
|
filterset_class = ReferenceitemFilter
|
||||||
|
search_fields = ["name"]
|
||||||
|
ordering_fields = ["name", "order", "type"]
|
||||||
|
ordering = ["order", "name"]
|
||||||
|
|
||||||
|
action_permission_classes = {}
|
||||||
|
action_serializer_class = {
|
||||||
|
"list": ListReferenceitemSerializer,
|
||||||
|
"retrieve": RetrieveReferenceitemSerializer,
|
||||||
|
"create": CreateReferenceitemSerializer,
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user