# /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 String, Integer, Boolean, DateTime, ForeignKey, text, Index, UniqueConstraint, Text 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): """ Robot v1.1.0 Multi-Tier MDM Master Adattábla. Az ökoszisztéma technikai igazságforrása. """ __tablename__ = "vehicle_model_definitions" 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()) # --- 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) # --- 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', name='uix_vmd_precision'), 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")