import uuid from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, Numeric, text, Text, UniqueConstraint from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import UUID as PG_UUID, JSONB from sqlalchemy.sql import func from app.db.base_class import Base class AssetCatalog(Base): __tablename__ = "vehicle_catalog" __table_args__ = ( UniqueConstraint( 'make', 'model', 'year_from', 'engine_variant', 'fuel_type', name='uix_vehicle_catalog_full' ), {"schema": "data"} ) id = Column(Integer, primary_key=True, index=True) make = Column(String, index=True, nullable=False) model = Column(String, index=True, nullable=False) generation = Column(String, index=True) engine_variant = Column(String, index=True) year_from = Column(Integer) year_to = Column(Integer) vehicle_class = Column(String) fuel_type = Column(String, index=True) # --- ÚJ OSZLOPOK (Ezeket add hozzá!) --- power_kw = Column(Integer, index=True) engine_capacity = Column(Integer, index=True) max_weight_kg = Column(Integer) axle_count = Column(Integer) euro_class = Column(String(20)) body_type = Column(String(100)) # --------------------------------------- engine_code = Column(String) factory_data = Column(JSONB, server_default=text("'{}'::jsonb")) assets = relationship("Asset", back_populates="catalog") class Asset(Base): __tablename__ = "assets" __table_args__ = {"schema": "data"} id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) vin = Column(String(17), unique=True, index=True, nullable=False) license_plate = Column(String(20), index=True) name = Column(String) year_of_manufacture = Column(Integer) current_organization_id = Column(Integer, ForeignKey("data.organizations.id"), nullable=True) catalog_id = Column(Integer, ForeignKey("data.vehicle_catalog.id")) # Moderációs mezők a Robot 3 (OCR) számára is_verified = Column(Boolean, default=False) verification_method = Column(String(20)) # 'manual', 'ocr', 'vin_api' verification_notes = Column(Text, nullable=True) # Eltérések jegyzőkönyve catalog_match_score = Column(Numeric(5, 2), nullable=True) # 0-100% egyezési arány status = Column(String(20), default="active") created_at = Column(DateTime(timezone=True), server_default=func.now()) updated_at = Column(DateTime(timezone=True), onupdate=func.now()) catalog = relationship("AssetCatalog", back_populates="assets") current_org = relationship("Organization") financials = relationship("AssetFinancials", back_populates="asset", uselist=False) telemetry = relationship("AssetTelemetry", back_populates="asset", uselist=False) assignments = relationship("AssetAssignment", back_populates="asset") events = relationship("AssetEvent", back_populates="asset") costs = relationship("AssetCost", back_populates="asset") reviews = relationship("AssetReview", back_populates="asset") ownership_history = relationship("VehicleOwnership", back_populates="vehicle") class AssetFinancials(Base): __tablename__ = "asset_financials" __table_args__ = {"schema": "data"} id = Column(Integer, primary_key=True) asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), unique=True) acquisition_price = Column(Numeric(18, 2)) acquisition_date = Column(DateTime) financing_type = Column(String) residual_value_estimate = Column(Numeric(18, 2)) asset = relationship("Asset", back_populates="financials") class AssetTelemetry(Base): __tablename__ = "asset_telemetry" __table_args__ = {"schema": "data"} id = Column(Integer, primary_key=True) asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), unique=True) current_mileage = Column(Integer, default=0) mileage_unit = Column(String(10), default="km") vqi_score = Column(Numeric(5, 2), default=100.00) dbs_score = Column(Numeric(5, 2), default=100.00) asset = relationship("Asset", back_populates="telemetry") class AssetReview(Base): __tablename__ = "asset_reviews" __table_args__ = {"schema": "data"} id = Column(Integer, primary_key=True) asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), nullable=False) user_id = Column(Integer, ForeignKey("data.users.id"), nullable=False) overall_rating = Column(Integer) criteria_scores = Column(JSONB, server_default=text("'{}'::jsonb")) comment = Column(Text) created_at = Column(DateTime(timezone=True), server_default=func.now()) asset = relationship("Asset", back_populates="reviews") user = relationship("User") class AssetAssignment(Base): __tablename__ = "asset_assignments" __table_args__ = {"schema": "data"} id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), nullable=False) organization_id = Column(Integer, ForeignKey("data.organizations.id"), nullable=False) # ÚJ: Telephelyi hozzárendelés branch_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.branches.id"), nullable=True) assigned_at = Column(DateTime(timezone=True), server_default=func.now()) released_at = Column(DateTime(timezone=True), nullable=True) status = Column(String(30), default="active") asset = relationship("Asset", back_populates="assignments") organization = relationship("Organization") branch = relationship("Branch") # Új kapcsolat class AssetEvent(Base): __tablename__ = "asset_events" __table_args__ = {"schema": "data"} id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), nullable=False) event_type = Column(String(50), nullable=False) recorded_mileage = Column(Integer) data = Column(JSONB, server_default=text("'{}'::jsonb")) asset = relationship("Asset", back_populates="events") class AssetCost(Base): __tablename__ = "asset_costs" __table_args__ = {"schema": "data"} id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), nullable=False) organization_id = Column(Integer, ForeignKey("data.organizations.id"), nullable=False) driver_id = Column(Integer, ForeignKey("data.users.id"), nullable=True) cost_type = Column(String(50), nullable=False) amount_local = Column(Numeric(18, 2), nullable=False) currency_local = Column(String(3), nullable=False) amount_eur = Column(Numeric(18, 2), nullable=True) net_amount_local = Column(Numeric(18, 2)) vat_rate = Column(Numeric(5, 2)) exchange_rate_used = Column(Numeric(18, 6)) date = Column(DateTime(timezone=True), server_default=func.now()) mileage_at_cost = Column(Integer) data = Column(JSONB, server_default=text("'{}'::jsonb")) asset = relationship("Asset", back_populates="costs") organization = relationship("Organization") driver = relationship("User") class ExchangeRate(Base): __tablename__ = "exchange_rates" __table_args__ = {"schema": "data"} id = Column(Integer, primary_key=True) base_currency = Column(String(3), default="EUR") target_currency = Column(String(3), unique=True) rate = Column(Numeric(18, 6), nullable=False) class CatalogDiscovery(Base): """ Discovery tábla: Ide gyűjtjük a piaci 'neveket' (pl. Citroen C3). A Robot innen indulva keresi meg az összes létező technikai variánst. """ __tablename__ = "catalog_discovery" id = Column(Integer, primary_key=True, index=True) make = Column(String(100), nullable=False, index=True) model = Column(String(100), nullable=False, index=True) vehicle_class = Column(String(50), index=True) # car, motorcycle, truck, stb. source = Column(String(50)) # 'hasznaltauto', 'mobile.de' status = Column(String(20), server_default=text("'pending'"), index=True) attempts = Column(Integer, default=0) last_attempt = Column(DateTime(timezone=True)) created_at = Column(DateTime(timezone=True), server_default=func.now()) # EGYESÍTETT __table_args__ __table_args__ = ( UniqueConstraint('make', 'model', 'vehicle_class', name='_make_model_class_uc'), {"schema": "data"} )