feat: add empty_weigh and full_weight fields for auto and mechanic rvalution models

This commit is contained in:
xoliqberdiyev
2026-05-06 15:12:46 +05:00
parent a17c2a52ce
commit 23b8c1450f
10 changed files with 123 additions and 79 deletions

View File

@@ -1,33 +0,0 @@
from datetime import date
import requests
CBU_URL = "https://cbu.uz/oz/arkhiv-kursov-valyut/json/{code}/{date}/"
TIMEOUT_SECONDS = 5
CURRENCY_CODES = ("USD", "EUR", "RUB")
def fetch_rates(target_date):
"""CBU.uz dan berilgan sanaga oid USD, EUR, RUB kurslarini olish.
Tarmoq xatosi yoki notogri javob bolsa bosh dict qaytadi.
"""
if target_date is None:
target_date = date.today()
date_str = target_date.strftime("%Y-%m-%d")
rates = {}
for code in CURRENCY_CODES:
try:
resp = requests.get(
CBU_URL.format(code=code, date=date_str),
timeout=TIMEOUT_SECONDS,
)
resp.raise_for_status()
data = resp.json()
if isinstance(data, list) and data:
rate_value = data[0].get("Rate")
if rate_value:
rates[code] = rate_value
except (requests.RequestException, ValueError):
continue
return rates

View File

@@ -12,7 +12,7 @@ from weasyprint import HTML
from core.apps.evaluation.models import AutoEvaluationModel from core.apps.evaluation.models import AutoEvaluationModel
from core.apps.evaluation.choices.auto import ObjectOwnerType from core.apps.evaluation.choices.auto import ObjectOwnerType
from core.apps.documents.serializers.contract import ContractPDFRequestSerializer from core.apps.documents.serializers.contract import ContractPDFRequestSerializer
from core.apps.documents.services.cbu_rates import fetch_rates from core.services import CurrencyService
UZ_MONTHS = { UZ_MONTHS = {
@@ -301,8 +301,8 @@ class ValuationReportPDFView(APIView):
"tech_passport": tech_passport_value, "tech_passport": tech_passport_value,
"fuel_type": fuel_type_value, "fuel_type": fuel_type_value,
"engine_power": "", "engine_power": "",
"full_weight": "", "full_weight": auto.full_weight if auto.full_weight is not None else "",
"empty_weight": "", "empty_weight": auto.empty_weight if auto.empty_weight is not None else "",
} }
def _customer_context(self, user): def _customer_context(self, user):
@@ -365,7 +365,7 @@ class ValuationReportPDFView(APIView):
} }
def _rates_context(self, target_date): def _rates_context(self, target_date):
rates = fetch_rates(target_date) rates = CurrencyService.get_rates(target_date)
return { return {
"rur": rates.get("RUB", ""), "rur": rates.get("RUB", ""),
"usd": rates.get("USD", ""), "usd": rates.get("USD", ""),

View File

@@ -0,0 +1,31 @@
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("evaluation", "0046_mechanicauto_fields_and_multi_tex_passport"),
]
operations = [
migrations.AddField(
model_name="autoevaluationmodel",
name="full_weight",
field=models.PositiveIntegerField(blank=True, null=True, verbose_name="full weight"),
),
migrations.AddField(
model_name="autoevaluationmodel",
name="empty_weight",
field=models.PositiveIntegerField(blank=True, null=True, verbose_name="empty weight"),
),
migrations.AddField(
model_name="mechanicautoevaluationmodel",
name="full_weight",
field=models.PositiveIntegerField(blank=True, null=True, verbose_name="full weight"),
),
migrations.AddField(
model_name="mechanicautoevaluationmodel",
name="empty_weight",
field=models.PositiveIntegerField(blank=True, null=True, verbose_name="empty weight"),
),
]

View File

@@ -260,6 +260,16 @@ class AutoEvaluationModel(AbstractBaseModel):
blank=True, blank=True,
null=True, null=True,
) )
full_weight = models.PositiveIntegerField(
verbose_name=_("full weight"),
blank=True,
null=True,
)
empty_weight = models.PositiveIntegerField(
verbose_name=_("empty weight"),
blank=True,
null=True,
)
# ── Natija ─────────────────────────────────────────────────────── # ── Natija ───────────────────────────────────────────────────────
rating_goal = models.CharField( rating_goal = models.CharField(

View File

@@ -256,6 +256,16 @@ class MechanicAutoEvaluationModel(AbstractBaseModel):
blank=True, blank=True,
null=True, null=True,
) )
full_weight = models.PositiveIntegerField(
verbose_name=_("full weight"),
blank=True,
null=True,
)
empty_weight = models.PositiveIntegerField(
verbose_name=_("empty weight"),
blank=True,
null=True,
)
# ── Natija ─────────────────────────────────────────────────────── # ── Natija ───────────────────────────────────────────────────────
rating_goal = models.CharField( rating_goal = models.CharField(

View File

@@ -73,6 +73,8 @@ class BaseAutoevaluationSerializer(serializers.ModelSerializer):
"car_number", "car_number",
"manufacture_year", "manufacture_year",
"car_color", "car_color",
"full_weight",
"empty_weight",
"distance_covered", "distance_covered",
"car_position", "car_position",
"body_type", "body_type",
@@ -214,6 +216,8 @@ class UpdateAutoevaluationSerializer(serializers.ModelSerializer):
"manufacture_year", "manufacture_year",
"car_dvigatel_number", "car_dvigatel_number",
"car_color", "car_color",
"full_weight",
"empty_weight",
"distance_covered", "distance_covered",
"car_position", "car_position",
"body_type", "body_type",
@@ -361,6 +365,8 @@ class CreateAutoevaluationSerializer(serializers.ModelSerializer):
"manufacture_year", "manufacture_year",
"car_dvigatel_number", "car_dvigatel_number",
"car_color", "car_color",
"full_weight",
"empty_weight",
"distance_covered", "distance_covered",
"car_position", "car_position",
"body_type", "body_type",
@@ -493,6 +499,8 @@ class AutoEvaluationModelSerializer(serializers.ModelSerializer):
"manufacture_year", "manufacture_year",
"car_dvigatel_number", "car_dvigatel_number",
"car_color", "car_color",
"full_weight",
"empty_weight",
"distance_covered", "distance_covered",
"car_position", "car_position",
"body_type", "body_type",

View File

@@ -73,6 +73,8 @@ class BaseMechanicAutoevaluationSerializer(serializers.ModelSerializer):
"car_number", "car_number",
"manufacture_year", "manufacture_year",
"car_color", "car_color",
"full_weight",
"empty_weight",
"distance_covered", "distance_covered",
"car_position", "car_position",
"body_type", "body_type",
@@ -213,6 +215,8 @@ class UpdateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
"manufacture_year", "manufacture_year",
"car_dvigatel_number", "car_dvigatel_number",
"car_color", "car_color",
"full_weight",
"empty_weight",
"distance_covered", "distance_covered",
"car_position", "car_position",
"body_type", "body_type",
@@ -363,6 +367,8 @@ class CreateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
"manufacture_year", "manufacture_year",
"car_dvigatel_number", "car_dvigatel_number",
"car_color", "car_color",
"full_weight",
"empty_weight",
"distance_covered", "distance_covered",
"car_position", "car_position",
"body_type", "body_type",
@@ -480,6 +486,8 @@ class MechanicAutoEvaluationModelSerializer(serializers.ModelSerializer):
"manufacture_year", "manufacture_year",
"car_dvigatel_number", "car_dvigatel_number",
"car_color", "car_color",
"full_weight",
"empty_weight",
"distance_covered", "distance_covered",
"car_position", "car_position",
"body_type", "body_type",

View File

@@ -3,3 +3,4 @@ from .sms import * # noqa
from .user import * # noqa from .user import * # noqa
from .didox import * # noqa from .didox import * # noqa
from .tech_passport import * # noqa from .tech_passport import * # noqa
from .currency import * # noqa

33
core/services/currency.py Normal file
View File

@@ -0,0 +1,33 @@
from datetime import date
import requests
import logging
logger = logging.getLogger(__name__)
class CurrencyService:
BASE_URL = "https://cbu.uz/oz/arkhiv-kursov-valyut/json"
CODES = ("USD", "EUR", "RUB")
TIMEOUT_SECONDS = 5
@classmethod
def get_rates(cls, target_date=None) -> dict:
if target_date is None:
target_date = date.today()
date_str = target_date.strftime("%Y-%m-%d")
rates = {}
for code in cls.CODES:
url = f"{cls.BASE_URL}/{code}/{date_str}/"
try:
response = requests.get(url, timeout=cls.TIMEOUT_SECONDS)
response.raise_for_status()
payload = response.json()
if isinstance(payload, list) and payload:
rate_value = payload[0].get("Rate")
if rate_value:
rates[code] = rate_value
except (requests.RequestException, ValueError) as e:
logger.exception(f"CBU API error for {code}: {e}")
return rates

View File

@@ -1,41 +1,17 @@
object_type => Bu hozirda select. Oshanga value qoshish kerak: bus, moto #Done 1. Valyutalarni kursini olish uchun API topib, malumotlarni pdfga yozish kerak
2. Foydalanuvchi ma'lumotlarni jshir orqali Didox apidan olib uni saqlab, keyin pdfga yozish kerak
3. Bajaruvchi ma'lumotlarni qoshish, tahrishlash uchun model yozishimiz kerak, va uni pdfga yozish kerak
4. Son korinishidan yozuv korinishiga o'tkazadigan funksiya yozish kerak, misol uchun 30 000 000 => "o'ttiz million"
car_position => Qoshish kerak. Bu hozirda select. /api/v1/reference-item/ apidan value yuboraman 5. Transport ma'lumotlarni tex passport orqali API dan olib uni saqlab, keyin pdfga yozish kerak
6. Obyektning textnik xolatini serializer orqali tanlaydigan qilish kerak va html filedagi yozilgan tabledagi malumotlarga quyidagicha ozgartirish kerak:
Har bir agregat bo'yicha ko'rik ro'yxati:
- Shinalar ko'rigi: tanlangan xolat
distance_covered => Qoshish kerak. Number. Bosib otilgan masofasi - Dvigatel ishlashini ko'rik: tanlangan xolat
- Yurish qismining ko'rigi: tanlangan xolat
- Transmissiya ko'rigi: tanlangan xolat
- Kuzov ko'rigi: tanlangan xolat
body_type => Qoshish kerak. Bu hozirda select. /api/v1/reference-item/ apidan value yuboraman 7. Baholanishi kerak bolgan mashinaning yangisini malumotlarni kerak. Shuning uchun yangi model ochib, kerakli malumotlarni toldiradigan qilish kerak
8. Eskirish koeffitsiyentlarini belgilash yani qanchadan qanchagacha necha foiz olishini yozish uchun model kerak
9. Solishtirma tahlil jadvali uchun analoglarni olib kelish kerak uzxariddan
10. Solishtirma tahlil jadvali uchun analoglar topilmasa, analoglarni qolda qoshadigan qilish kerak, keyin analoglar bilan birga rasmlar ham yuklay olishi kerak
fuel_type => Qoshish kerak. Bu hozirda select. /api/v1/reference-item/ apidan value yuboraman 11. QR code generate qilib pdfning har bir sahifasining ong tomon pastki qismiga joylashtirish kerak va https://{domain}/q/auto-basic/:id manashu urlga redirect qilishi kerak
state_car => Qoshish kerak. Bu hozirda select. /api/v1/reference-item/ apidan value yuboraman
car_type => manashu field ni olib tashlash kerak
tex_passport_file => multiple qilish kerak
assessment_task_type => Baholash vazifasi. Qoshish kerak. Select boladi. /api/v1/reference-item/ apidan value yuboraman
object_owner_residence => Obyekt egasi yashash joyi. Qoshish kerak. string boladi.
manashu fieldlarni detail apidagi serializerga qoshish kerak auto-evaluationda ham va mechnic-auto-evaluationda ham