# /opt/docker/dev/service_finder/backend/app/models/vehicle_definitions.py from __future__ import annotations from datetime import datetime from typing import Optional, List from sqlalchemy import Column, String, Integer, Boolean, DateTime, ForeignKey, text, JSON, Index, UniqueConstraint, Text, ARRAY, func, Numeric from sqlalchemy.orm import Mapped, mapped_column, relationship from sqlalchemy.dialects.postgresql import JSONB from sqlalchemy.sql import func # MB 2.0: Egységesített Base import a központi adatbázis motorból from app.database import Base class VehicleType(Base): """ Jármű kategóriák (pl. Személyautó, Motorkerékpár, Teherautó, Hajó) """ __tablename__ = "vehicle_types" __table_args__ = {"schema": "data"} id: Mapped[int] = mapped_column(Integer, primary_key=True) code: Mapped[str] = mapped_column(String(30), unique=True, index=True) name: Mapped[str] = mapped_column(String(50)) icon: Mapped[Optional[str]] = mapped_column(String(50)) units: Mapped[dict] = mapped_column(JSONB, server_default=text("'{\"power\": \"kW\", \"weight\": \"kg\"}'::jsonb")) # Kapcsolatok features: Mapped[List["FeatureDefinition"]] = relationship("FeatureDefinition", back_populates="vehicle_type") definitions: Mapped[List["VehicleModelDefinition"]] = relationship("VehicleModelDefinition", back_populates="v_type_rel") class FeatureDefinition(Base): """ Felszereltségi elemek definíciója (pl. ABS, Klíma, LED fényszóró) """ __tablename__ = "feature_definitions" __table_args__ = {"schema": "data"} id: Mapped[int] = mapped_column(Integer, primary_key=True) vehicle_type_id: Mapped[int] = mapped_column(Integer, ForeignKey("data.vehicle_types.id")) code: Mapped[str] = mapped_column(String(50), index=True) name: Mapped[str] = mapped_column(String(100)) category: Mapped[str] = mapped_column(String(50), index=True) vehicle_type: Mapped["VehicleType"] = relationship("VehicleType", back_populates="features") model_maps: Mapped[List["ModelFeatureMap"]] = relationship("ModelFeatureMap", back_populates="feature") class VehicleModelDefinition(Base): market: Mapped[str] = mapped_column(String(20), server_default=text("'GLOBAL'"), index=True) """ Robot v1.1.0 Multi-Tier MDM Master Adattábla. Az ökoszisztéma technikai igazságforrása. """ __tablename__ = "vehicle_model_definitions" __table_args__ = {"schema": "data"} id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True) make: Mapped[str] = mapped_column(String(100), index=True) marketing_name: Mapped[str] = mapped_column(String(255), index=True) # Nyers név az RDW-ből official_marketing_name: Mapped[Optional[str]] = mapped_column(String(255)) # Dúsított, validált név (Robot 2.2) # --- ROBOT LOGIKAI MEZŐK (JAVÍTVA 2.0 STÍLUSBAN) --- attempts: Mapped[int] = mapped_column(Integer, default=0, server_default=text("0")) last_error: Mapped[Optional[str]] = mapped_column(Text, nullable=True) updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), onupdate=func.now(), server_default=func.now()) priority_score: Mapped[int] = mapped_column(Integer, default=0, server_default=text("0")) # --- PRECISION LOGIC MEZŐK --- normalized_name: Mapped[Optional[str]] = mapped_column(String(255), index=True, nullable=True) marketing_name_aliases: Mapped[list] = mapped_column(JSONB, server_default=text("'[]'::jsonb")) engine_code: Mapped[Optional[str]] = mapped_column(String(50), index=True) # A GLOBÁLIS KAPOCS # --- TECHNIKAI AZONOSÍTÓK --- technical_code: Mapped[str] = mapped_column(String(100), index=True) # Holland rendszám (kulcs) variant_code: Mapped[Optional[str]] = mapped_column(String(100), index=True) version_code: Mapped[Optional[str]] = mapped_column(String(100), index=True) # --- ÚJ PRÉMIUM MŰSZAKI MEZŐK --- type_approval_number: Mapped[Optional[str]] = mapped_column(String(100), index=True) # e1*2001/... seats: Mapped[Optional[int]] = mapped_column(Integer) width: Mapped[Optional[int]] = mapped_column(Integer) # cm wheelbase: Mapped[Optional[int]] = mapped_column(Integer) # cm list_price: Mapped[Optional[int]] = mapped_column(Integer) # EUR (catalogusprijs) max_speed: Mapped[Optional[int]] = mapped_column(Integer) # km/h # Vontatási adatok towing_weight_unbraked: Mapped[Optional[int]] = mapped_column(Integer) towing_weight_braked: Mapped[Optional[int]] = mapped_column(Integer) # Környezetvédelmi adatok fuel_consumption_combined: Mapped[Optional[float]] = mapped_column(Numeric(10, 2), nullable=True) co2_emissions_combined: Mapped[Optional[int]] = mapped_column(Integer) # --- SPECIFIKÁCIÓK --- vehicle_type_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("data.vehicle_types.id")) vehicle_class: Mapped[Optional[str]] = mapped_column(String(50), index=True) body_type: Mapped[Optional[str]] = mapped_column(String(100)) fuel_type: Mapped[Optional[str]] = mapped_column(String(50), index=True) engine_capacity: Mapped[int] = mapped_column(Integer, default=0, index=True) power_kw: Mapped[int] = mapped_column(Integer, default=0, index=True) torque_nm: Mapped[Optional[int]] = mapped_column(Integer) cylinders: Mapped[Optional[int]] = mapped_column(Integer) cylinder_layout: Mapped[Optional[str]] = mapped_column(String(50)) curb_weight: Mapped[Optional[int]] = mapped_column(Integer) max_weight: Mapped[Optional[int]] = mapped_column(Integer) euro_classification: Mapped[Optional[str]] = mapped_column(String(20)) doors: Mapped[Optional[int]] = mapped_column(Integer) transmission_type: Mapped[Optional[str]] = mapped_column(String(50)) drive_type: Mapped[Optional[str]] = mapped_column(String(50)) # --- ÉLETCIKLUS ÉS STÁTUSZ --- year_from: Mapped[Optional[int]] = mapped_column(Integer, index=True) year_to: Mapped[Optional[int]] = mapped_column(Integer, index=True) production_status: Mapped[Optional[str]] = mapped_column(String(50)) # active / discontinued # Státusz szintek: unverified, research_in_progress, awaiting_ai_synthesis, gold_enriched status: Mapped[str] = mapped_column(String(50), server_default=text("'unverified'"), index=True) is_manual: Mapped[bool] = mapped_column(Boolean, default=False) source: Mapped[Optional[str]] = mapped_column(String(100)) # --- ADAT-KONTÉNEREK --- raw_search_context: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb")) research_metadata: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb")) specifications: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb")) # Robot 2.2/2.5 Arany adatai created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) last_research_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True)) # --- BEÁLLÍTÁSOK --- __table_args__ = ( UniqueConstraint('make', 'normalized_name', 'variant_code', 'version_code', 'fuel_type', 'market', 'year_from', name='uix_vmd_precision_v2'), Index('idx_vmd_lookup_fast', 'make', 'normalized_name'), Index('idx_vmd_engine_bridge', 'make', 'engine_code'), {"schema": "data"} ) # KAPCSOLATOK v_type_rel: Mapped["VehicleType"] = relationship("VehicleType", back_populates="definitions") feature_maps: Mapped[List["ModelFeatureMap"]] = relationship("ModelFeatureMap", back_populates="model_definition") # Hivatkozás az asset.py-ban lévő osztályra # Megjegyzés: Ha az AssetCatalog nincs itt importálva, húzzal adjuk meg a nevet variants: Mapped[List["AssetCatalog"]] = relationship("AssetCatalog", back_populates="master_definition") class ModelFeatureMap(Base): """ Kapcsolótábla a modellek és az alapfelszereltség között """ __tablename__ = "model_feature_maps" __table_args__ = {"schema": "data"} id: Mapped[int] = mapped_column(Integer, primary_key=True) model_definition_id: Mapped[int] = mapped_column(Integer, ForeignKey("data.vehicle_model_definitions.id")) feature_id: Mapped[int] = mapped_column(Integer, ForeignKey("data.feature_definitions.id")) is_standard: Mapped[bool] = mapped_column(Boolean, default=True) model_definition: Mapped["VehicleModelDefinition"] = relationship("VehicleModelDefinition", back_populates="feature_maps") feature: Mapped["FeatureDefinition"] = relationship("FeatureDefinition", back_populates="model_maps")