Files
superDreamFront/app/models/__init__.py
2026-04-15 21:35:26 +08:00

88 lines
4.4 KiB
Python

from __future__ import annotations
import uuid
from datetime import datetime
from decimal import Decimal
from typing import List
from sqlalchemy import String, Text, Integer, BigInteger, DateTime, Numeric, Enum, ForeignKey, Index, func
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.core.database import Base
class User(Base):
__tablename__ = "users"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
email: Mapped[str] = mapped_column(String(255), unique=True, nullable=False, index=True)
password_hash: Mapped[str] = mapped_column(String(255), nullable=False)
balance: Mapped[Decimal] = mapped_column(Numeric(16, 6), default=Decimal("0"))
status: Mapped[str] = mapped_column(String(20), default="active") # active / disabled
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now())
api_keys: Mapped[List[ApiKey]] = relationship(back_populates="user")
transactions: Mapped[List[Transaction]] = relationship(back_populates="user")
class ApiKey(Base):
__tablename__ = "api_keys"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
user_id: Mapped[str] = mapped_column(String(36), ForeignKey("users.id"), nullable=False, index=True)
name: Mapped[str] = mapped_column(String(100), default="")
key_hash: Mapped[str] = mapped_column(String(64), unique=True, nullable=False) # SHA256
key_prefix: Mapped[str] = mapped_column(String(10), nullable=False)
key_suffix: Mapped[str] = mapped_column(String(10), nullable=False)
status: Mapped[str] = mapped_column(String(20), default="active") # active / revoked
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
user: Mapped["User"] = relationship(back_populates="api_keys")
class UsageLog(Base):
__tablename__ = "usage_logs"
__table_args__ = (
Index("ix_usage_user_time", "user_id", "request_time"),
Index("ix_usage_model", "user_id", "model"),
)
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
user_id: Mapped[str] = mapped_column(String(36), ForeignKey("users.id"), nullable=False)
key_id: Mapped[str] = mapped_column(String(36), ForeignKey("api_keys.id"), nullable=False)
model: Mapped[str] = mapped_column(String(100), nullable=False)
prompt_tokens: Mapped[int] = mapped_column(Integer, default=0)
completion_tokens: Mapped[int] = mapped_column(Integer, default=0)
total_tokens: Mapped[int] = mapped_column(Integer, default=0)
cost: Mapped[Decimal] = mapped_column(Numeric(16, 6), default=Decimal("0"))
request_time: Mapped[datetime] = mapped_column(DateTime, nullable=False)
response_time: Mapped[datetime] = mapped_column(DateTime, nullable=True)
status: Mapped[str] = mapped_column(String(20), default="success") # success / error
class Transaction(Base):
__tablename__ = "transactions"
id: Mapped[str] = mapped_column(String(36), primary_key=True, default=lambda: str(uuid.uuid4()))
user_id: Mapped[str] = mapped_column(String(36), ForeignKey("users.id"), nullable=False, index=True)
type: Mapped[str] = mapped_column(String(20), nullable=False) # topup / consume / refund
amount: Mapped[Decimal] = mapped_column(Numeric(16, 6), nullable=False)
balance_after: Mapped[Decimal] = mapped_column(Numeric(16, 6), nullable=False)
reference_id: Mapped[str] = mapped_column(String(100), default="")
created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
user: Mapped["User"] = relationship(back_populates="transactions")
class ModelPricing(Base):
__tablename__ = "models_pricing"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
model_name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False)
provider: Mapped[str] = mapped_column(String(50), nullable=False)
input_price_per_1k: Mapped[Decimal] = mapped_column(Numeric(16, 6), nullable=False)
output_price_per_1k: Mapped[Decimal] = mapped_column(Numeric(16, 6), nullable=False)
status: Mapped[str] = mapped_column(String(20), default="available") # available / offline
updated_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), onupdate=func.now())