from datetime import datetime from decimal import Decimal from sqlalchemy import ( JSON, Boolean, DateTime, ForeignKey, Integer, Numeric, String, UniqueConstraint, func, ) from sqlalchemy.orm import Mapped, mapped_column from app.db.base import Base class Achievement(Base): __tablename__ = "achievements" id: Mapped[int] = mapped_column(primary_key=True) code: Mapped[str] = mapped_column(String(80), unique=True, index=True) scope: Mapped[str] = mapped_column(String(24), default="user", server_default="user", index=True) title: Mapped[str] = mapped_column(String(120)) description: Mapped[str] = mapped_column(String(260)) icon: Mapped[str | None] = mapped_column(String(40)) category: Mapped[str | None] = mapped_column(String(40), index=True) is_active: Mapped[bool] = mapped_column(Boolean, default=True, server_default="true", index=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) class UserAchievement(Base): __tablename__ = "user_achievements" __table_args__ = ( UniqueConstraint( "user_id", "achievement_id", "vehicle_id", "service_center_id", name="uq_user_achievement_scope", ), ) id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), index=True) achievement_id: Mapped[int] = mapped_column(ForeignKey("achievements.id", ondelete="CASCADE"), index=True) vehicle_id: Mapped[int | None] = mapped_column(ForeignKey("cars.id", ondelete="CASCADE"), index=True) service_center_id: Mapped[int | None] = mapped_column(ForeignKey("service_centers.id", ondelete="CASCADE"), index=True) unlocked_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), index=True) metadata_json: Mapped[dict | None] = mapped_column(JSON) class VehicleScore(Base): __tablename__ = "vehicle_scores" id: Mapped[int] = mapped_column(primary_key=True) vehicle_id: Mapped[int] = mapped_column(ForeignKey("cars.id", ondelete="CASCADE"), unique=True, index=True) completeness_score: Mapped[int] = mapped_column(Integer, default=0, server_default="0") verified_history_score: Mapped[int] = mapped_column(Integer, default=0, server_default="0") maintenance_health_score: Mapped[int] = mapped_column(Integer, default=100, server_default="100") maintenance_status: Mapped[str] = mapped_column(String(24), default="unknown", server_default="unknown", index=True) profile_quality: Mapped[str] = mapped_column(String(40), default="basic", server_default="basic", index=True) verified_history_status: Mapped[str] = mapped_column(String(40), default="self_reported", server_default="self_reported", index=True) missing_items: Mapped[list | None] = mapped_column(JSON) computed_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) class ServiceCenterScore(Base): __tablename__ = "service_center_scores" id: Mapped[int] = mapped_column(primary_key=True) service_center_id: Mapped[int] = mapped_column( ForeignKey("service_centers.id", ondelete="CASCADE"), unique=True, index=True ) trust_score: Mapped[int] = mapped_column(Integer, default=0, server_default="0") trust_level: Mapped[str] = mapped_column(String(40), default="new_service", server_default="new_service", index=True) confirmed_visits_count: Mapped[int] = mapped_column(Integer, default=0, server_default="0") confirmation_rate: Mapped[Decimal] = mapped_column(Numeric(5, 2), default=0, server_default="0") dispute_rate: Mapped[Decimal] = mapped_column(Numeric(5, 2), default=0, server_default="0") computed_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) class EngagementEvent(Base): __tablename__ = "engagement_events" id: Mapped[int] = mapped_column(primary_key=True) user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), index=True) vehicle_id: Mapped[int | None] = mapped_column(ForeignKey("cars.id", ondelete="CASCADE"), index=True) service_center_id: Mapped[int | None] = mapped_column(ForeignKey("service_centers.id", ondelete="CASCADE"), index=True) event_type: Mapped[str] = mapped_column(String(80), index=True) metadata_json: Mapped[dict | None] = mapped_column(JSON) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), index=True)