feat: wire contract PDF context and align MechanicAuto with AutoEvaluation
- contract PDF: map report/customer/owner/contract from AutoEvaluationModel fields, accept inspection via POST serializer, fetch CBU.uz currency rates - MechanicAutoEvaluation: add distance_covered, object_owner_residence and car_position/body_type/fuel_type/state_car/assessment_task_type FKs; drop car_type and single tex_passport_file in favour of multi-file FK model Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
0
core/apps/documents/serializers/__init__.py
Normal file
0
core/apps/documents/serializers/__init__.py
Normal file
13
core/apps/documents/serializers/contract.py
Normal file
13
core/apps/documents/serializers/contract.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
|
||||||
|
class InspectionSerializer(serializers.Serializer):
|
||||||
|
tires = serializers.CharField(required=False, allow_blank=True, default="Qoniqarli")
|
||||||
|
engine = serializers.CharField(required=False, allow_blank=True, default="Qoniqarli")
|
||||||
|
chassis = serializers.CharField(required=False, allow_blank=True, default="Qoniqarli")
|
||||||
|
transmission = serializers.CharField(required=False, allow_blank=True, default="Qoniqarli")
|
||||||
|
body = serializers.CharField(required=False, allow_blank=True, default="Qoniqarli")
|
||||||
|
|
||||||
|
|
||||||
|
class ContractPDFRequestSerializer(serializers.Serializer):
|
||||||
|
inspection = InspectionSerializer(required=False)
|
||||||
0
core/apps/documents/services/__init__.py
Normal file
0
core/apps/documents/services/__init__.py
Normal file
33
core/apps/documents/services/cbu_rates.py
Normal file
33
core/apps/documents/services/cbu_rates.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
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
|
||||||
@@ -10,6 +10,9 @@ from rest_framework import status
|
|||||||
from weasyprint import HTML
|
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.documents.serializers.contract import ContractPDFRequestSerializer
|
||||||
|
from core.apps.documents.services.cbu_rates import fetch_rates
|
||||||
|
|
||||||
|
|
||||||
UZ_MONTHS = {
|
UZ_MONTHS = {
|
||||||
@@ -27,6 +30,14 @@ UZ_TENS = [
|
|||||||
"oltmish", "yetmish", "sakson", "to'qson",
|
"oltmish", "yetmish", "sakson", "to'qson",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
DEFAULT_INSPECTION = {
|
||||||
|
"tires": "Qoniqarli",
|
||||||
|
"engine": "Qoniqarli",
|
||||||
|
"chassis": "Qoniqarli",
|
||||||
|
"transmission": "Qoniqarli",
|
||||||
|
"body": "Qoniqarli",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def _format_currency(value):
|
def _format_currency(value):
|
||||||
if value is None:
|
if value is None:
|
||||||
@@ -97,33 +108,44 @@ class ValuationReportPDFView(APIView):
|
|||||||
"""
|
"""
|
||||||
Baholash hisobotini PDF formatida yuklab olish uchun API.
|
Baholash hisobotini PDF formatida yuklab olish uchun API.
|
||||||
|
|
||||||
GET /api/documents/generate-contract-pdf/<pk>/
|
GET /api/documents/generate-contract-pdf/<pk>/
|
||||||
pk — AutoEvaluationModel id si.
|
POST /api/documents/generate-contract-pdf/<pk>/
|
||||||
|
|
||||||
|
POST so'rov tanasida inspection malumotlarini yuborish mumkin:
|
||||||
|
{
|
||||||
|
"inspection": {
|
||||||
|
"tires": "...",
|
||||||
|
"engine": "...",
|
||||||
|
"chassis": "...",
|
||||||
|
"transmission": "...",
|
||||||
|
"body": "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get(self, request, pk, *args, **kwargs):
|
def get(self, request, pk, *args, **kwargs):
|
||||||
return self._generate_pdf(request, pk)
|
return self._generate_pdf(request, pk, payload={})
|
||||||
|
|
||||||
def post(self, request, pk, *args, **kwargs):
|
def post(self, request, pk, *args, **kwargs):
|
||||||
return self._generate_pdf(request, pk)
|
serializer = ContractPDFRequestSerializer(data=request.data or {})
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
return self._generate_pdf(request, pk, payload=serializer.validated_data)
|
||||||
|
|
||||||
def _generate_pdf(self, request, pk):
|
def _generate_pdf(self, request, pk, payload):
|
||||||
auto_evaluation = get_object_or_404(
|
auto_evaluation = get_object_or_404(
|
||||||
AutoEvaluationModel.objects.select_related(
|
AutoEvaluationModel.objects.select_related(
|
||||||
|
"user",
|
||||||
"vehicle",
|
"vehicle",
|
||||||
"vehicle__brand",
|
"vehicle__brand",
|
||||||
"vehicle__model",
|
"vehicle__model",
|
||||||
"vehicle__color",
|
"vehicle__color",
|
||||||
"vehicle__fuel_type",
|
"vehicle__fuel_type",
|
||||||
"vehicle__body_type",
|
"vehicle__body_type",
|
||||||
"valuation",
|
|
||||||
"valuation__customer",
|
|
||||||
"valuation__property_owner",
|
|
||||||
),
|
),
|
||||||
pk=pk,
|
pk=pk,
|
||||||
)
|
)
|
||||||
|
|
||||||
context = self._build_context(auto_evaluation)
|
context = self._build_context(auto_evaluation, payload)
|
||||||
|
|
||||||
html_string = render_to_string("documents/contract.html", context)
|
html_string = render_to_string("documents/contract.html", context)
|
||||||
base_url = request.build_absolute_uri("/")
|
base_url = request.build_absolute_uri("/")
|
||||||
@@ -144,95 +166,34 @@ class ValuationReportPDFView(APIView):
|
|||||||
response["Content-Length"] = len(pdf_file)
|
response["Content-Length"] = len(pdf_file)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
def _build_context(self, auto):
|
def _build_context(self, auto, payload):
|
||||||
vehicle = auto.vehicle
|
vehicle = auto.vehicle
|
||||||
valuation = auto.valuation
|
user = auto.user
|
||||||
customer = valuation.customer if valuation else None
|
|
||||||
owner = valuation.property_owner if valuation and valuation.property_owner else customer
|
|
||||||
report = getattr(valuation, "report", None) if valuation else None
|
|
||||||
|
|
||||||
report_date = (
|
report_date = auto.rate_report_date or auto.contract_date or date.today()
|
||||||
auto.rate_report_date
|
|
||||||
or auto.contract_date
|
|
||||||
or (report.created_at.date() if report else None)
|
|
||||||
or date.today()
|
|
||||||
)
|
|
||||||
valuation_date = auto.rate_date or report_date
|
valuation_date = auto.rate_date or report_date
|
||||||
inspection_date = auto.object_inspection_date or report_date
|
inspection_date = auto.object_inspection_date or report_date
|
||||||
|
|
||||||
report_number = (
|
report_number = auto.registration_number or f"{auto.pk}/{report_date.year}"
|
||||||
(report.report_number if report else None)
|
|
||||||
or auto.registration_number
|
|
||||||
or (valuation.conclusion_number if valuation else None)
|
|
||||||
or f"{auto.pk}/{report_date.year}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
# Bozor qiymati hozircha hisoblanmagan — default 0.
|
||||||
final_value = None
|
final_value = None
|
||||||
if report and report.final_value is not None:
|
|
||||||
final_value = report.final_value
|
|
||||||
elif valuation and valuation.final_price is not None:
|
|
||||||
final_value = valuation.final_price
|
|
||||||
elif valuation and valuation.estimated_price is not None:
|
|
||||||
final_value = valuation.estimated_price
|
|
||||||
|
|
||||||
market_value_formatted = (
|
market_value_formatted = (
|
||||||
f"{_format_currency(final_value)} so'm" if final_value is not None else "0 so'm"
|
f"{_format_currency(final_value)} so'm" if final_value is not None else "0 so'm"
|
||||||
)
|
)
|
||||||
market_value_words = (
|
market_value_words = (
|
||||||
f"{_number_to_uzbek_words(final_value)} so'm"
|
f"{_number_to_uzbek_words(final_value)} so'm" if final_value is not None else ""
|
||||||
if final_value is not None
|
|
||||||
else ""
|
|
||||||
)
|
)
|
||||||
|
|
||||||
cost_final = final_value
|
cost_final = final_value
|
||||||
comparative_final = final_value
|
comparative_final = final_value
|
||||||
|
|
||||||
brand_name = ""
|
vehicle_ctx = self._vehicle_context(auto, vehicle)
|
||||||
model_name = ""
|
customer_ctx = self._customer_context(user)
|
||||||
if vehicle:
|
owner_ctx = self._owner_context(auto)
|
||||||
brand_name = vehicle.brand.name if vehicle.brand else ""
|
|
||||||
model_name = vehicle.model.name if vehicle.model else ""
|
|
||||||
if not brand_name:
|
|
||||||
brand_name = auto.car_brand or ""
|
|
||||||
if not model_name:
|
|
||||||
model_name = auto.car_model or ""
|
|
||||||
full_brand = f"{brand_name} {model_name}".strip()
|
|
||||||
|
|
||||||
plate_number = (vehicle.license_plate if vehicle else None) or auto.car_number or ""
|
|
||||||
manufacture_year = ""
|
|
||||||
if vehicle and vehicle.manufacture_year:
|
|
||||||
manufacture_year = str(vehicle.manufacture_year)
|
|
||||||
elif auto.manufacture_year:
|
|
||||||
manufacture_year = str(auto.manufacture_year)
|
|
||||||
|
|
||||||
production_date = f"{manufacture_year}-yil" if manufacture_year else ""
|
|
||||||
engine_number = (vehicle.engine_number if vehicle else None) or auto.car_dvigatel_number or ""
|
|
||||||
body_number = vehicle.vin_number if vehicle and vehicle.vin_number else ""
|
|
||||||
color_value = ""
|
|
||||||
if vehicle and vehicle.color:
|
|
||||||
color_value = vehicle.color.name
|
|
||||||
elif auto.car_color:
|
|
||||||
color_value = auto.car_color
|
|
||||||
fuel_type_value = ""
|
|
||||||
if vehicle and vehicle.fuel_type:
|
|
||||||
fuel_type_value = vehicle.fuel_type.name
|
|
||||||
|
|
||||||
tech_passport_value = ""
|
|
||||||
if vehicle and (vehicle.tech_passport_series or vehicle.tech_passport_number):
|
|
||||||
tech_passport_value = (
|
|
||||||
f"{vehicle.tech_passport_series or ''} № {vehicle.tech_passport_number or ''}"
|
|
||||||
).strip()
|
|
||||||
elif auto.tex_passport_serie_num:
|
|
||||||
tech_passport_value = auto.tex_passport_serie_num
|
|
||||||
|
|
||||||
customer_ctx = self._customer_context(customer)
|
|
||||||
owner_ctx = self._owner_context(owner)
|
|
||||||
if not owner_ctx["name"]:
|
|
||||||
owner_ctx = customer_ctx
|
|
||||||
|
|
||||||
contract_ctx = self._contract_context(auto, report_date)
|
contract_ctx = self._contract_context(auto, report_date)
|
||||||
|
inspection_ctx = self._inspection_context(payload)
|
||||||
director_name = customer.director_name if customer and customer.director_name else "—"
|
rates_ctx = self._rates_context(valuation_date)
|
||||||
|
|
||||||
ctx = {
|
ctx = {
|
||||||
"logo_url": "",
|
"logo_url": "",
|
||||||
@@ -241,44 +202,19 @@ class ValuationReportPDFView(APIView):
|
|||||||
"date": _format_date(report_date),
|
"date": _format_date(report_date),
|
||||||
"valuation_date": _format_date(valuation_date),
|
"valuation_date": _format_date(valuation_date),
|
||||||
"inspection_date": _format_date(inspection_date),
|
"inspection_date": _format_date(inspection_date),
|
||||||
"year": str(report_date.year),
|
"year": str(report_date.year or date.today().year),
|
||||||
"market_value_formatted": market_value_formatted,
|
"market_value_formatted": market_value_formatted,
|
||||||
"market_value_words": market_value_words,
|
"market_value_words": market_value_words,
|
||||||
},
|
},
|
||||||
"vehicle": {
|
"vehicle": vehicle_ctx,
|
||||||
"brand": full_brand,
|
|
||||||
"plate_number": plate_number,
|
|
||||||
"production_date": production_date,
|
|
||||||
"production_year": manufacture_year,
|
|
||||||
"type": auto.get_object_type_display() if auto.object_type else "",
|
|
||||||
"engine_number": engine_number,
|
|
||||||
"body_number": body_number,
|
|
||||||
"chassis_number": body_number,
|
|
||||||
"color": color_value,
|
|
||||||
"tech_passport": tech_passport_value,
|
|
||||||
"fuel_type": fuel_type_value,
|
|
||||||
"engine_power": "",
|
|
||||||
"full_weight": "",
|
|
||||||
"empty_weight": "",
|
|
||||||
},
|
|
||||||
"customer": customer_ctx,
|
"customer": customer_ctx,
|
||||||
"owner": owner_ctx,
|
"owner": owner_ctx,
|
||||||
"contract": contract_ctx,
|
"contract": contract_ctx,
|
||||||
"company": {
|
"company": {
|
||||||
"director": director_name,
|
"director": "—",
|
||||||
},
|
|
||||||
"rates": {
|
|
||||||
"rur": "",
|
|
||||||
"usd": "",
|
|
||||||
"eur": "",
|
|
||||||
},
|
|
||||||
"inspection": {
|
|
||||||
"tires": "",
|
|
||||||
"engine": "",
|
|
||||||
"chassis": "",
|
|
||||||
"transmission": "",
|
|
||||||
"body": "",
|
|
||||||
},
|
},
|
||||||
|
"rates": rates_ctx,
|
||||||
|
"inspection": inspection_ctx,
|
||||||
"cost": {
|
"cost": {
|
||||||
"engine_volume": "",
|
"engine_volume": "",
|
||||||
"factory_price": _format_currency(cost_final),
|
"factory_price": _format_currency(cost_final),
|
||||||
@@ -311,7 +247,65 @@ class ValuationReportPDFView(APIView):
|
|||||||
}
|
}
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
def _customer_context(self, customer):
|
def _vehicle_context(self, auto, vehicle):
|
||||||
|
brand_name = ""
|
||||||
|
model_name = ""
|
||||||
|
if vehicle:
|
||||||
|
brand_name = vehicle.brand.name if vehicle.brand else ""
|
||||||
|
model_name = vehicle.model.name if vehicle.model else ""
|
||||||
|
if not brand_name:
|
||||||
|
brand_name = auto.car_brand or ""
|
||||||
|
if not model_name:
|
||||||
|
model_name = auto.car_model or ""
|
||||||
|
full_brand = f"{brand_name} {model_name}".strip()
|
||||||
|
|
||||||
|
plate_number = (vehicle.license_plate if vehicle else None) or auto.car_number or ""
|
||||||
|
manufacture_year = ""
|
||||||
|
if vehicle and vehicle.manufacture_year:
|
||||||
|
manufacture_year = str(vehicle.manufacture_year)
|
||||||
|
elif auto.manufacture_year:
|
||||||
|
manufacture_year = str(auto.manufacture_year)
|
||||||
|
|
||||||
|
production_date = f"{manufacture_year}-yil" if manufacture_year else ""
|
||||||
|
engine_number = (vehicle.engine_number if vehicle else None) or auto.car_dvigatel_number or ""
|
||||||
|
body_number = vehicle.vin_number if vehicle and vehicle.vin_number else ""
|
||||||
|
|
||||||
|
color_value = ""
|
||||||
|
if vehicle and vehicle.color:
|
||||||
|
color_value = vehicle.color.name
|
||||||
|
elif auto.car_color:
|
||||||
|
color_value = auto.car_color
|
||||||
|
|
||||||
|
fuel_type_value = ""
|
||||||
|
if vehicle and vehicle.fuel_type:
|
||||||
|
fuel_type_value = vehicle.fuel_type.name
|
||||||
|
|
||||||
|
tech_passport_value = ""
|
||||||
|
if vehicle and (vehicle.tech_passport_series or vehicle.tech_passport_number):
|
||||||
|
tech_passport_value = (
|
||||||
|
f"{vehicle.tech_passport_series or ''} № {vehicle.tech_passport_number or ''}"
|
||||||
|
).strip()
|
||||||
|
elif auto.tex_passport_serie_num:
|
||||||
|
tech_passport_value = auto.tex_passport_serie_num
|
||||||
|
|
||||||
|
return {
|
||||||
|
"brand": full_brand,
|
||||||
|
"plate_number": plate_number,
|
||||||
|
"production_date": production_date,
|
||||||
|
"production_year": manufacture_year,
|
||||||
|
"type": auto.get_object_type_display() if auto.object_type else "",
|
||||||
|
"engine_number": engine_number,
|
||||||
|
"body_number": body_number,
|
||||||
|
"chassis_number": body_number,
|
||||||
|
"color": color_value,
|
||||||
|
"tech_passport": tech_passport_value,
|
||||||
|
"fuel_type": fuel_type_value,
|
||||||
|
"engine_power": "",
|
||||||
|
"full_weight": "",
|
||||||
|
"empty_weight": "",
|
||||||
|
}
|
||||||
|
|
||||||
|
def _customer_context(self, user):
|
||||||
empty = {
|
empty = {
|
||||||
"name": "",
|
"name": "",
|
||||||
"address": "",
|
"address": "",
|
||||||
@@ -321,51 +315,41 @@ class ValuationReportPDFView(APIView):
|
|||||||
"bank": "",
|
"bank": "",
|
||||||
"mfo": "",
|
"mfo": "",
|
||||||
}
|
}
|
||||||
if not customer:
|
if not user:
|
||||||
return empty
|
return empty
|
||||||
if customer.customer_type == "legal":
|
full_name = " ".join(filter(None, [user.last_name, user.first_name])).strip()
|
||||||
return {
|
if not full_name:
|
||||||
"name": customer.org_name or "",
|
full_name = user.username or user.phone or ""
|
||||||
"address": customer.org_address or "",
|
|
||||||
"phone": "",
|
|
||||||
"tin": customer.inn or "",
|
|
||||||
"account": customer.bank_account or "",
|
|
||||||
"bank": "",
|
|
||||||
"mfo": customer.mfo or "",
|
|
||||||
}
|
|
||||||
full_name = " ".join(
|
|
||||||
filter(None, [customer.last_name, customer.first_name, customer.middle_name])
|
|
||||||
)
|
|
||||||
return {
|
return {
|
||||||
"name": full_name,
|
"name": full_name,
|
||||||
"address": customer.address or "",
|
"address": "",
|
||||||
"phone": "",
|
"phone": user.phone or "",
|
||||||
"tin": customer.jshshir or "",
|
"tin": "",
|
||||||
"account": "",
|
"account": "",
|
||||||
"bank": "",
|
"bank": "",
|
||||||
"mfo": "",
|
"mfo": "",
|
||||||
}
|
}
|
||||||
|
|
||||||
def _owner_context(self, owner):
|
def _owner_context(self, auto):
|
||||||
empty = {"name": "", "address": ""}
|
if auto.object_owner_type == ObjectOwnerType.LEGAL:
|
||||||
if not owner:
|
|
||||||
return empty
|
|
||||||
type_field = getattr(owner, "owner_type", None) or getattr(owner, "customer_type", None)
|
|
||||||
if type_field == "legal":
|
|
||||||
return {
|
return {
|
||||||
"name": owner.org_name or "",
|
"name": auto.object_owner_legal_entity or "",
|
||||||
"address": owner.org_address or "",
|
"address": auto.object_owner_residence or "",
|
||||||
}
|
}
|
||||||
full_name = " ".join(
|
full_name = " ".join(
|
||||||
filter(None, [owner.last_name, owner.first_name, owner.middle_name])
|
filter(None, [
|
||||||
)
|
auto.object_owner_individual_person_l_name,
|
||||||
|
auto.object_owner_individual_person_f_name,
|
||||||
|
auto.object_owner_individual_person_p_name,
|
||||||
|
])
|
||||||
|
).strip()
|
||||||
return {
|
return {
|
||||||
"name": full_name,
|
"name": full_name,
|
||||||
"address": owner.address or "",
|
"address": auto.object_owner_residence or "",
|
||||||
}
|
}
|
||||||
|
|
||||||
def _contract_context(self, auto, fallback_date):
|
def _contract_context(self, auto, fallback_date):
|
||||||
contract_date = auto.contract_date or fallback_date
|
contract_date = auto.contract_date or auto.rate_report_date or fallback_date
|
||||||
return {
|
return {
|
||||||
"number": auto.registration_number or str(auto.pk),
|
"number": auto.registration_number or str(auto.pk),
|
||||||
"day": f"{contract_date.day:02d}",
|
"day": f"{contract_date.day:02d}",
|
||||||
@@ -373,6 +357,21 @@ class ValuationReportPDFView(APIView):
|
|||||||
"year": str(contract_date.year),
|
"year": str(contract_date.year),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def _inspection_context(self, payload):
|
||||||
|
provided = (payload or {}).get("inspection") or {}
|
||||||
|
return {
|
||||||
|
key: provided.get(key) or default
|
||||||
|
for key, default in DEFAULT_INSPECTION.items()
|
||||||
|
}
|
||||||
|
|
||||||
|
def _rates_context(self, target_date):
|
||||||
|
rates = fetch_rates(target_date)
|
||||||
|
return {
|
||||||
|
"rur": rates.get("RUB", ""),
|
||||||
|
"usd": rates.get("USD", ""),
|
||||||
|
"eur": rates.get("EUR", ""),
|
||||||
|
}
|
||||||
|
|
||||||
def _empty_analog(self):
|
def _empty_analog(self):
|
||||||
return {
|
return {
|
||||||
"source": "",
|
"source": "",
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("evaluation", "0045_alter_referenceitemmodel_type"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="car_type",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="tex_passport_file",
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="distance_covered",
|
||||||
|
field=models.PositiveIntegerField(blank=True, null=True, verbose_name="distance covered"),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="object_owner_residence",
|
||||||
|
field=models.CharField(blank=True, max_length=255, null=True, verbose_name="object owner residence"),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="car_position",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name="evaluation_mechanic_auto_car_position",
|
||||||
|
to="evaluation.referenceitemmodel",
|
||||||
|
verbose_name="car position",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="body_type",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name="evaluation_mechanic_auto_body_type",
|
||||||
|
to="evaluation.referenceitemmodel",
|
||||||
|
verbose_name="body type",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="fuel_type",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name="evaluation_mechanic_auto_fuel_type",
|
||||||
|
to="evaluation.referenceitemmodel",
|
||||||
|
verbose_name="fuel type",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="state_car",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name="evaluation_mechanic_auto_state_car",
|
||||||
|
to="evaluation.referenceitemmodel",
|
||||||
|
verbose_name="state car",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="mechanicautoevaluationmodel",
|
||||||
|
name="assessment_task_type",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
related_name="evaluation_mechanic_auto_assessment_task_type",
|
||||||
|
to="evaluation.referenceitemmodel",
|
||||||
|
verbose_name="assessment task type",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="MechanicAutoEvaluationTexPassportFile",
|
||||||
|
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)),
|
||||||
|
(
|
||||||
|
"file",
|
||||||
|
models.FileField(
|
||||||
|
upload_to="mechanic_evaluation/tech_passports/%Y/%m/",
|
||||||
|
verbose_name="tech passport file",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"mechanic_auto_evaluation",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="tex_passport_files",
|
||||||
|
to="evaluation.mechanicautoevaluationmodel",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Mechanic Auto Evaluation Tex Passport File",
|
||||||
|
"verbose_name_plural": "Mechanic Auto Evaluation Tex Passport Files",
|
||||||
|
"db_table": "MechanicAutoEvaluationTexPassportFile",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -4,7 +4,6 @@ from django_core.models import AbstractBaseModel
|
|||||||
from model_bakery import baker
|
from model_bakery import baker
|
||||||
|
|
||||||
from core.apps.evaluation.choices.auto import (
|
from core.apps.evaluation.choices.auto import (
|
||||||
AutoCarType,
|
|
||||||
AutoCarWheel,
|
AutoCarWheel,
|
||||||
AutoEvaluationStatus,
|
AutoEvaluationStatus,
|
||||||
AutoObjectType,
|
AutoObjectType,
|
||||||
@@ -50,12 +49,57 @@ class MechanicAutoEvaluationModel(AbstractBaseModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
tex_passport_file = models.FileField(
|
distance_covered = models.PositiveIntegerField(
|
||||||
verbose_name=_("tech passport file"),
|
verbose_name=_("distance covered"),
|
||||||
upload_to="mechanic_evaluation/tech_passports/%Y/%m/",
|
|
||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
|
object_owner_residence = models.CharField(
|
||||||
|
verbose_name=_("object owner residence"),
|
||||||
|
max_length=255,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
)
|
||||||
|
car_position = models.ForeignKey(
|
||||||
|
'evaluation.ReferenceitemModel',
|
||||||
|
verbose_name=_("car position"),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name='evaluation_mechanic_auto_car_position',
|
||||||
|
)
|
||||||
|
body_type = models.ForeignKey(
|
||||||
|
'evaluation.ReferenceitemModel',
|
||||||
|
verbose_name=_("body type"),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name='evaluation_mechanic_auto_body_type',
|
||||||
|
)
|
||||||
|
fuel_type = models.ForeignKey(
|
||||||
|
'evaluation.ReferenceitemModel',
|
||||||
|
verbose_name=_("fuel type"),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name='evaluation_mechanic_auto_fuel_type',
|
||||||
|
)
|
||||||
|
state_car = models.ForeignKey(
|
||||||
|
'evaluation.ReferenceitemModel',
|
||||||
|
verbose_name=_("state car"),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name='evaluation_mechanic_auto_state_car',
|
||||||
|
)
|
||||||
|
assessment_task_type = models.ForeignKey(
|
||||||
|
'evaluation.ReferenceitemModel',
|
||||||
|
verbose_name=_("assessment task type"),
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
|
related_name='evaluation_mechanic_auto_assessment_task_type',
|
||||||
|
)
|
||||||
|
|
||||||
# ── Step 1 — Umumiy ma'lumotlar ──────────────────────────────────
|
# ── Step 1 — Umumiy ma'lumotlar ──────────────────────────────────
|
||||||
registration_number = models.CharField(
|
registration_number = models.CharField(
|
||||||
@@ -170,12 +214,6 @@ class MechanicAutoEvaluationModel(AbstractBaseModel):
|
|||||||
blank=True,
|
blank=True,
|
||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
car_type = models.IntegerField(
|
|
||||||
verbose_name=_("car type"),
|
|
||||||
choices=AutoCarType.choices,
|
|
||||||
blank=True,
|
|
||||||
null=True,
|
|
||||||
)
|
|
||||||
car_wheel = models.IntegerField(
|
car_wheel = models.IntegerField(
|
||||||
verbose_name=_("car wheel"),
|
verbose_name=_("car wheel"),
|
||||||
choices=AutoCarWheel.choices,
|
choices=AutoCarWheel.choices,
|
||||||
@@ -248,3 +286,27 @@ class MechanicAutoEvaluationModel(AbstractBaseModel):
|
|||||||
db_table = "MechanicAutoEvaluation"
|
db_table = "MechanicAutoEvaluation"
|
||||||
verbose_name = _("Mechanic Auto Evaluation")
|
verbose_name = _("Mechanic Auto Evaluation")
|
||||||
verbose_name_plural = _("Mechanic Auto Evaluations")
|
verbose_name_plural = _("Mechanic Auto Evaluations")
|
||||||
|
|
||||||
|
|
||||||
|
class MechanicAutoEvaluationTexPassportFile(AbstractBaseModel):
|
||||||
|
mechanic_auto_evaluation = models.ForeignKey(
|
||||||
|
MechanicAutoEvaluationModel,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="tex_passport_files",
|
||||||
|
)
|
||||||
|
file = models.FileField(
|
||||||
|
verbose_name=_("tech passport file"),
|
||||||
|
upload_to="mechanic_evaluation/tech_passports/%Y/%m/",
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"Tex passport file for MechanicAutoEvaluation #{self.mechanic_auto_evaluation_id}"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _baker(cls):
|
||||||
|
return baker.make(cls)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = "MechanicAutoEvaluationTexPassportFile"
|
||||||
|
verbose_name = _("Mechanic Auto Evaluation Tex Passport File")
|
||||||
|
verbose_name_plural = _("Mechanic Auto Evaluation Tex Passport Files")
|
||||||
|
|||||||
@@ -3,9 +3,12 @@ import re
|
|||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from django.db import transaction
|
||||||
|
|
||||||
from core.apps.evaluation.choices.request import RequestStatus
|
from core.apps.evaluation.choices.request import RequestStatus
|
||||||
from core.apps.evaluation.models import (
|
from core.apps.evaluation.models import (
|
||||||
MechanicAutoEvaluationModel,
|
MechanicAutoEvaluationModel,
|
||||||
|
MechanicAutoEvaluationTexPassportFile,
|
||||||
ReferenceitemModel,
|
ReferenceitemModel,
|
||||||
EvaluationrequestModel,
|
EvaluationrequestModel,
|
||||||
)
|
)
|
||||||
@@ -14,6 +17,22 @@ from core.apps.evaluation.serializers.reference import ListReferenceitemSerializ
|
|||||||
User = get_user_model()
|
User = get_user_model()
|
||||||
|
|
||||||
|
|
||||||
|
class MechanicAutoEvaluationTexPassportFileSerializer(serializers.ModelSerializer):
|
||||||
|
file = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = MechanicAutoEvaluationTexPassportFile
|
||||||
|
fields = ["id", "file"]
|
||||||
|
|
||||||
|
def get_file(self, obj):
|
||||||
|
request = self.context.get("request")
|
||||||
|
if not obj.file:
|
||||||
|
return None
|
||||||
|
if request:
|
||||||
|
return request.build_absolute_uri(obj.file.url)
|
||||||
|
return obj.file.url
|
||||||
|
|
||||||
|
|
||||||
class BaseMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
class BaseMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
||||||
status_display = serializers.CharField(source="get_status_display", read_only=True)
|
status_display = serializers.CharField(source="get_status_display", read_only=True)
|
||||||
object_type_display = serializers.CharField(source="get_object_type_display", read_only=True, default=None)
|
object_type_display = serializers.CharField(source="get_object_type_display", read_only=True, default=None)
|
||||||
@@ -21,6 +40,12 @@ class BaseMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
default=None)
|
default=None)
|
||||||
rate_type = ListReferenceitemSerializer(read_only=True)
|
rate_type = ListReferenceitemSerializer(read_only=True)
|
||||||
value_determined = ListReferenceitemSerializer(read_only=True)
|
value_determined = ListReferenceitemSerializer(read_only=True)
|
||||||
|
car_position = ListReferenceitemSerializer(read_only=True)
|
||||||
|
body_type = ListReferenceitemSerializer(read_only=True)
|
||||||
|
fuel_type = ListReferenceitemSerializer(read_only=True)
|
||||||
|
state_car = ListReferenceitemSerializer(read_only=True)
|
||||||
|
assessment_task_type = ListReferenceitemSerializer(read_only=True)
|
||||||
|
tex_passport_files = MechanicAutoEvaluationTexPassportFileSerializer(many=True, read_only=True)
|
||||||
user = serializers.SerializerMethodField(method_name="get_user", read_only=True)
|
user = serializers.SerializerMethodField(method_name="get_user", read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -36,7 +61,9 @@ class BaseMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
"object_owner_individual_person_p_name",
|
"object_owner_individual_person_p_name",
|
||||||
"object_owner_legal_entity",
|
"object_owner_legal_entity",
|
||||||
"object_owner_legal_inn",
|
"object_owner_legal_inn",
|
||||||
|
"object_owner_residence",
|
||||||
"tex_passport_serie_num",
|
"tex_passport_serie_num",
|
||||||
|
"tex_passport_files",
|
||||||
"rating_goal",
|
"rating_goal",
|
||||||
"registration_number",
|
"registration_number",
|
||||||
"object_type",
|
"object_type",
|
||||||
@@ -46,6 +73,12 @@ class BaseMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
"car_number",
|
"car_number",
|
||||||
"manufacture_year",
|
"manufacture_year",
|
||||||
"car_color",
|
"car_color",
|
||||||
|
"distance_covered",
|
||||||
|
"car_position",
|
||||||
|
"body_type",
|
||||||
|
"fuel_type",
|
||||||
|
"state_car",
|
||||||
|
"assessment_task_type",
|
||||||
"status",
|
"status",
|
||||||
"status_display",
|
"status_display",
|
||||||
"created_at",
|
"created_at",
|
||||||
@@ -72,7 +105,6 @@ class ListMechanicAutoevaluationSerializer(BaseMechanicAutoevaluationSerializer)
|
|||||||
|
|
||||||
|
|
||||||
class RetrieveMechanicAutoevaluationSerializer(BaseMechanicAutoevaluationSerializer):
|
class RetrieveMechanicAutoevaluationSerializer(BaseMechanicAutoevaluationSerializer):
|
||||||
car_type_display = serializers.CharField(source="get_car_type_display", read_only=True, default=None)
|
|
||||||
car_wheel_display = serializers.CharField(source="get_car_wheel_display", read_only=True, default=None)
|
car_wheel_display = serializers.CharField(source="get_car_wheel_display", read_only=True, default=None)
|
||||||
|
|
||||||
class Meta(BaseMechanicAutoevaluationSerializer.Meta):
|
class Meta(BaseMechanicAutoevaluationSerializer.Meta):
|
||||||
@@ -90,11 +122,8 @@ class RetrieveMechanicAutoevaluationSerializer(BaseMechanicAutoevaluationSeriali
|
|||||||
"object_owner_legal_entity",
|
"object_owner_legal_entity",
|
||||||
"object_owner_legal_inn",
|
"object_owner_legal_inn",
|
||||||
"tex_passport_serie_num",
|
"tex_passport_serie_num",
|
||||||
"tex_passport_file",
|
|
||||||
"tex_passport_gived_date",
|
"tex_passport_gived_date",
|
||||||
"tex_passport_gived_location",
|
"tex_passport_gived_location",
|
||||||
"car_type",
|
|
||||||
"car_type_display",
|
|
||||||
"car_wheel",
|
"car_wheel",
|
||||||
"car_wheel_display",
|
"car_wheel_display",
|
||||||
"car_dvigatel_number",
|
"car_dvigatel_number",
|
||||||
@@ -116,11 +145,41 @@ class UpdateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
required=False,
|
required=False,
|
||||||
allow_null=True,
|
allow_null=True,
|
||||||
)
|
)
|
||||||
|
car_position = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
|
body_type = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
|
fuel_type = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
|
state_car = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
|
assessment_task_type = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
user = serializers.PrimaryKeyRelatedField(
|
user = serializers.PrimaryKeyRelatedField(
|
||||||
queryset=User.objects.all(),
|
queryset=User.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
allow_null=True,
|
allow_null=True,
|
||||||
)
|
)
|
||||||
|
tex_passport_files = serializers.ListField(
|
||||||
|
child=serializers.FileField(),
|
||||||
|
required=False,
|
||||||
|
write_only=True,
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MechanicAutoEvaluationModel
|
model = MechanicAutoEvaluationModel
|
||||||
@@ -139,13 +198,14 @@ class UpdateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
"object_owner_individual_person_passport_num",
|
"object_owner_individual_person_passport_num",
|
||||||
"object_owner_legal_entity",
|
"object_owner_legal_entity",
|
||||||
"object_owner_legal_inn",
|
"object_owner_legal_inn",
|
||||||
|
"object_owner_residence",
|
||||||
"value_determined",
|
"value_determined",
|
||||||
"rate_type",
|
"rate_type",
|
||||||
"tex_passport_file",
|
"assessment_task_type",
|
||||||
|
"tex_passport_files",
|
||||||
"tex_passport_serie_num",
|
"tex_passport_serie_num",
|
||||||
"tex_passport_gived_date",
|
"tex_passport_gived_date",
|
||||||
"tex_passport_gived_location",
|
"tex_passport_gived_location",
|
||||||
"car_type",
|
|
||||||
"car_wheel",
|
"car_wheel",
|
||||||
"car_brand",
|
"car_brand",
|
||||||
"car_model",
|
"car_model",
|
||||||
@@ -153,6 +213,11 @@ class UpdateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
"manufacture_year",
|
"manufacture_year",
|
||||||
"car_dvigatel_number",
|
"car_dvigatel_number",
|
||||||
"car_color",
|
"car_color",
|
||||||
|
"distance_covered",
|
||||||
|
"car_position",
|
||||||
|
"body_type",
|
||||||
|
"fuel_type",
|
||||||
|
"state_car",
|
||||||
]
|
]
|
||||||
|
|
||||||
def validate_tex_passport_serie_num(self, value):
|
def validate_tex_passport_serie_num(self, value):
|
||||||
@@ -197,6 +262,21 @@ class UpdateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
files = validated_data.pop("tex_passport_files", None)
|
||||||
|
with transaction.atomic():
|
||||||
|
for attr, value in validated_data.items():
|
||||||
|
setattr(instance, attr, value)
|
||||||
|
instance.save()
|
||||||
|
if files is not None:
|
||||||
|
MechanicAutoEvaluationTexPassportFile.objects.bulk_create([
|
||||||
|
MechanicAutoEvaluationTexPassportFile(mechanic_auto_evaluation=instance, file=f) for f in files
|
||||||
|
])
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
return RetrieveMechanicAutoevaluationSerializer(instance, context=self.context).data
|
||||||
|
|
||||||
|
|
||||||
class CreateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
class CreateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
||||||
value_determined = serializers.PrimaryKeyRelatedField(
|
value_determined = serializers.PrimaryKeyRelatedField(
|
||||||
@@ -209,6 +289,31 @@ class CreateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
required=False,
|
required=False,
|
||||||
allow_null=True,
|
allow_null=True,
|
||||||
)
|
)
|
||||||
|
car_position = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
|
body_type = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
|
fuel_type = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
|
state_car = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
|
assessment_task_type = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=ReferenceitemModel.objects.all(),
|
||||||
|
required=False,
|
||||||
|
allow_null=True,
|
||||||
|
)
|
||||||
evaluation_request = serializers.PrimaryKeyRelatedField(
|
evaluation_request = serializers.PrimaryKeyRelatedField(
|
||||||
queryset=EvaluationrequestModel.objects.all(),
|
queryset=EvaluationrequestModel.objects.all(),
|
||||||
required=False,
|
required=False,
|
||||||
@@ -219,6 +324,11 @@ class CreateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
required=True,
|
required=True,
|
||||||
allow_null=False,
|
allow_null=False,
|
||||||
)
|
)
|
||||||
|
tex_passport_files = serializers.ListField(
|
||||||
|
child=serializers.FileField(),
|
||||||
|
required=False,
|
||||||
|
write_only=True,
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = MechanicAutoEvaluationModel
|
model = MechanicAutoEvaluationModel
|
||||||
@@ -238,13 +348,14 @@ class CreateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
"object_owner_individual_person_passport_num",
|
"object_owner_individual_person_passport_num",
|
||||||
"object_owner_legal_entity",
|
"object_owner_legal_entity",
|
||||||
"object_owner_legal_inn",
|
"object_owner_legal_inn",
|
||||||
|
"object_owner_residence",
|
||||||
"value_determined",
|
"value_determined",
|
||||||
"rate_type",
|
"rate_type",
|
||||||
|
"assessment_task_type",
|
||||||
"tex_passport_serie_num",
|
"tex_passport_serie_num",
|
||||||
"tex_passport_file",
|
"tex_passport_files",
|
||||||
"tex_passport_gived_date",
|
"tex_passport_gived_date",
|
||||||
"tex_passport_gived_location",
|
"tex_passport_gived_location",
|
||||||
"car_type",
|
|
||||||
"car_wheel",
|
"car_wheel",
|
||||||
"car_brand",
|
"car_brand",
|
||||||
"car_model",
|
"car_model",
|
||||||
@@ -252,6 +363,11 @@ class CreateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
"manufacture_year",
|
"manufacture_year",
|
||||||
"car_dvigatel_number",
|
"car_dvigatel_number",
|
||||||
"car_color",
|
"car_color",
|
||||||
|
"distance_covered",
|
||||||
|
"car_position",
|
||||||
|
"body_type",
|
||||||
|
"fuel_type",
|
||||||
|
"state_car",
|
||||||
]
|
]
|
||||||
|
|
||||||
def validate_tex_passport_serie_num(self, value):
|
def validate_tex_passport_serie_num(self, value):
|
||||||
@@ -296,11 +412,21 @@ class CreateMechanicAutoevaluationSerializer(serializers.ModelSerializer):
|
|||||||
return attrs
|
return attrs
|
||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
|
files = validated_data.pop("tex_passport_files", [])
|
||||||
evaluation_req = validated_data.get("evaluation_request")
|
evaluation_req = validated_data.get("evaluation_request")
|
||||||
if evaluation_req:
|
if evaluation_req:
|
||||||
evaluation_req.status = RequestStatus.IN_PROGRESS
|
evaluation_req.status = RequestStatus.IN_PROGRESS
|
||||||
evaluation_req.save()
|
evaluation_req.save()
|
||||||
return super().create(validated_data)
|
with transaction.atomic():
|
||||||
|
instance = super().create(validated_data)
|
||||||
|
if files:
|
||||||
|
MechanicAutoEvaluationTexPassportFile.objects.bulk_create([
|
||||||
|
MechanicAutoEvaluationTexPassportFile(mechanic_auto_evaluation=instance, file=f) for f in files
|
||||||
|
])
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def to_representation(self, instance):
|
||||||
|
return RetrieveMechanicAutoevaluationSerializer(instance, context=self.context).data
|
||||||
|
|
||||||
|
|
||||||
class MechanicAutoEvaluationAppraisersSerializer(serializers.Serializer):
|
class MechanicAutoEvaluationAppraisersSerializer(serializers.Serializer):
|
||||||
@@ -327,7 +453,6 @@ class MechanicAutoEvaluationModelSerializer(serializers.ModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = MechanicAutoEvaluationModel
|
model = MechanicAutoEvaluationModel
|
||||||
fields = (
|
fields = (
|
||||||
"tex_passport_file",
|
|
||||||
"registration_number",
|
"registration_number",
|
||||||
"contract_date",
|
"contract_date",
|
||||||
"object_inspection_date",
|
"object_inspection_date",
|
||||||
@@ -341,12 +466,13 @@ class MechanicAutoEvaluationModelSerializer(serializers.ModelSerializer):
|
|||||||
"object_owner_individual_person_passport_num",
|
"object_owner_individual_person_passport_num",
|
||||||
"object_owner_legal_entity",
|
"object_owner_legal_entity",
|
||||||
"object_owner_legal_inn",
|
"object_owner_legal_inn",
|
||||||
|
"object_owner_residence",
|
||||||
"value_determined",
|
"value_determined",
|
||||||
"rate_type",
|
"rate_type",
|
||||||
|
"assessment_task_type",
|
||||||
"tex_passport_serie_num",
|
"tex_passport_serie_num",
|
||||||
"tex_passport_gived_date",
|
"tex_passport_gived_date",
|
||||||
"tex_passport_gived_location",
|
"tex_passport_gived_location",
|
||||||
"car_type",
|
|
||||||
"car_wheel",
|
"car_wheel",
|
||||||
"car_brand",
|
"car_brand",
|
||||||
"car_model",
|
"car_model",
|
||||||
@@ -354,6 +480,11 @@ class MechanicAutoEvaluationModelSerializer(serializers.ModelSerializer):
|
|||||||
"manufacture_year",
|
"manufacture_year",
|
||||||
"car_dvigatel_number",
|
"car_dvigatel_number",
|
||||||
"car_color",
|
"car_color",
|
||||||
|
"distance_covered",
|
||||||
|
"car_position",
|
||||||
|
"body_type",
|
||||||
|
"fuel_type",
|
||||||
|
"state_car",
|
||||||
"rating_goal",
|
"rating_goal",
|
||||||
"status",
|
"status",
|
||||||
"is_archived",
|
"is_archived",
|
||||||
|
|||||||
@@ -846,7 +846,7 @@
|
|||||||
© Ushbu hisobot mazmuni "SIFAT BAHOLASH" kompaniyasining mulki
|
© Ushbu hisobot mazmuni "SIFAT BAHOLASH" kompaniyasining mulki
|
||||||
hisoblanadi va<br />
|
hisoblanadi va<br />
|
||||||
ushbu hujjatning ruxsatsiz nusxalanishi noqonuniy hisoblanadi.
|
ushbu hujjatning ruxsatsiz nusxalanishi noqonuniy hisoblanadi.
|
||||||
<div class="city-year">Toshkent — {{ report.year }}</div>
|
<div class="city-year">Toshkent — 2026</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
42
task.txt
42
task.txt
@@ -1 +1,41 @@
|
|||||||
Refrence item model'ga "assessment_task_type" kategoriya qo'shish kerak
|
object_type => Bu hozirda select. O’shanga value qo’shish kerak: bus, moto
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
car_position => Qo’shish kerak. Bu hozirda select. /api/v1/reference-item/ api’dan value yuboraman
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
distance_covered => Qo’shish kerak. Number. Bosib o’tilgan masofasi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
body_type => Qo’shish kerak. Bu hozirda select. /api/v1/reference-item/ api’dan value yuboraman
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
fuel_type => Qo’shish kerak. Bu hozirda select. /api/v1/reference-item/ api’dan value yuboraman
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
state_car => Qo’shish kerak. Bu hozirda select. /api/v1/reference-item/ api’dan value yuboraman
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
car_type => manashu field ni olib tashlash kerak
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tex_passport_file => multiple qilish kerak
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assessment_task_type => Baholash vazifasi. Qo’shish kerak. Select bo’ladi. /api/v1/reference-item/ api’dan value yuboraman
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object_owner_residence => Obyekt egasi yashash joyi. Qo’shish kerak. string bo’ladi.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
manashu fieldlarni detail apidagi serializerga qoshish kerak auto-evaluationda ham va mechnic-auto-evaluationda ham
|
||||||
Reference in New Issue
Block a user