Files
drivers_bot/app/models/gamification.py
2026-05-12 20:06:25 +09:00

95 lines
4.6 KiB
Python

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)