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

Merged
xoliqberdiyev merged 1 commits from behruz into main 2026-05-06 10:13:31 +00:00
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.choices.auto import ObjectOwnerType
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 = {
@@ -301,8 +301,8 @@ class ValuationReportPDFView(APIView):
"tech_passport": tech_passport_value,
"fuel_type": fuel_type_value,
"engine_power": "",
"full_weight": "",
"empty_weight": "",
"full_weight": auto.full_weight if auto.full_weight is not None else "",
"empty_weight": auto.empty_weight if auto.empty_weight is not None else "",
}
def _customer_context(self, user):
@@ -365,7 +365,7 @@ class ValuationReportPDFView(APIView):
}
def _rates_context(self, target_date):
rates = fetch_rates(target_date)
rates = CurrencyService.get_rates(target_date)
return {
"rur": rates.get("RUB", ""),
"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,
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 ───────────────────────────────────────────────────────
rating_goal = models.CharField(

View File

@@ -256,6 +256,16 @@ class MechanicAutoEvaluationModel(AbstractBaseModel):
blank=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 ───────────────────────────────────────────────────────
rating_goal = models.CharField(

View File

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

View File

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

View File

@@ -3,3 +3,4 @@ from .sms import * # noqa
from .user import * # noqa
from .didox 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
car_position => Qoshish kerak. Bu hozirda select. /api/v1/reference-item/ apidan value yuboraman
distance_covered => Qoshish kerak. Number. Bosib otilgan masofasi
body_type => Qoshish kerak. Bu hozirda select. /api/v1/reference-item/ apidan value yuboraman
fuel_type => Qoshish kerak. Bu hozirda select. /api/v1/reference-item/ apidan value yuboraman
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
#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"
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
- Dvigatel ishlashini ko'rik: tanlangan xolat
- Yurish qismining ko'rigi: tanlangan xolat
- Transmissiya ko'rigi: tanlangan xolat
- Kuzov ko'rigi: tanlangan xolat
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
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