from datetime import datetime, date, timezone from decimal import Decimal from sqlalchemy import ( String, Boolean, Date, DateTime, DECIMAL, Integer, SmallInteger, ForeignKey, Text, JSON ) from sqlalchemy.orm import Mapped, mapped_column, relationship from app.core.database import Base class VehicleRegistry(Base): __tablename__ = "vehicle_registry" plate: Mapped[str] = mapped_column(String(10), primary_key=True) vin: Mapped[str | None] = mapped_column(String(17)) vehicle_type: Mapped[str | None] = mapped_column(String(50)) registration_date: Mapped[date | None] = mapped_column(Date) homologation_code: Mapped[str | None] = mapped_column(String(50)) engine_code: Mapped[str | None] = mapped_column(String(20)) last_revision_date: Mapped[date | None] = mapped_column(Date) foreign_plate: Mapped[str | None] = mapped_column(String(20)) foreign_registration_date: Mapped[date | None] = mapped_column(Date) foreign_country: Mapped[str | None] = mapped_column(String(50)) is_foreign_registered: Mapped[bool | None] = mapped_column(Boolean) source: Mapped[str | None] = mapped_column(String(20)) raw_response: Mapped[dict | None] = mapped_column(JSON) fetched_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) selected_motornet_code: Mapped[str | None] = mapped_column(String(20)) version_candidates: Mapped[list["PlateVersionCandidate"]] = relationship( "PlateVersionCandidate", back_populates="registry" ) class VehicleVersion(Base): __tablename__ = "vehicle_versions" motornet_code: Mapped[str] = mapped_column(String(20), primary_key=True) brand_acronym: Mapped[str | None] = mapped_column(String(10)) brand_name: Mapped[str | None] = mapped_column(String(50)) model_code: Mapped[str | None] = mapped_column(String(10)) model_description: Mapped[str | None] = mapped_column(String(100)) gamma_code: Mapped[str | None] = mapped_column(String(10)) gamma_description: Mapped[str | None] = mapped_column(String(100)) series_code: Mapped[str | None] = mapped_column(String(10)) series_description: Mapped[str | None] = mapped_column(String(100)) historical_group_code: Mapped[str | None] = mapped_column(String(10)) historical_group_desc: Mapped[str | None] = mapped_column(String(100)) cod_desc_model_code: Mapped[str | None] = mapped_column(String(10)) cod_desc_model_desc: Mapped[str | None] = mapped_column(String(100)) version_label: Mapped[str | None] = mapped_column(String(200)) body_type: Mapped[str | None] = mapped_column(String(10)) doors: Mapped[int | None] = mapped_column(SmallInteger) wheelbase: Mapped[int | None] = mapped_column(SmallInteger) list_price: Mapped[Decimal | None] = mapped_column(DECIMAL(10, 2)) production_start: Mapped[date | None] = mapped_column(Date) production_end: Mapped[date | None] = mapped_column(Date) commercial_start: Mapped[date | None] = mapped_column(Date) commercial_end: Mapped[date | None] = mapped_column(Date) first_seen_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) last_seen_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True)) seen_count: Mapped[int] = mapped_column(Integer, default=1) source: Mapped[str | None] = mapped_column(String(20)) plate_candidates: Mapped[list["PlateVersionCandidate"]] = relationship( "PlateVersionCandidate", back_populates="version" ) class PlateVersionCandidate(Base): __tablename__ = "plate_version_candidates" plate: Mapped[str] = mapped_column( String(10), ForeignKey("vehicle_registry.plate"), primary_key=True ) motornet_code: Mapped[str] = mapped_column( String(20), ForeignKey("vehicle_versions.motornet_code"), primary_key=True ) is_selected: Mapped[bool] = mapped_column(Boolean, default=False) registry: Mapped["VehicleRegistry"] = relationship( "VehicleRegistry", back_populates="version_candidates" ) version: Mapped["VehicleVersion"] = relationship( "VehicleVersion", back_populates="plate_candidates" ) class ApiUsageLog(Base): __tablename__ = "api_usage_log" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) source: Mapped[str | None] = mapped_column(String(20)) plate: Mapped[str | None] = mapped_column(String(10)) hit_cache: Mapped[bool] = mapped_column(Boolean, default=False) remaining_queries: Mapped[int | None] = mapped_column(Integer) called_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=lambda: datetime.now(timezone.utc) )