| from __future__ import annotations |
|
|
| from datetime import datetime |
|
|
| from sqlalchemy import DateTime, ForeignKey, Index, Integer, String, func |
| from sqlalchemy.orm import Mapped, mapped_column |
|
|
| from app.core.database import Base |
| from app.utils.ids import prefixed_id |
|
|
|
|
| class UserPlan(Base): |
| __tablename__ = "user_plans" |
|
|
| id: Mapped[str] = mapped_column( |
| String(40), |
| primary_key=True, |
| default=lambda: prefixed_id("plan"), |
| ) |
| user_id: Mapped[str] = mapped_column( |
| String(40), |
| ForeignKey("users.id"), |
| unique=True, |
| index=True, |
| nullable=False, |
| ) |
| selected_plan: Mapped[str] = mapped_column( |
| String(60), |
| default="free", |
| nullable=False, |
| ) |
| status: Mapped[str] = mapped_column( |
| String(40), |
| default="active", |
| nullable=False, |
| ) |
| trial_started_at: Mapped[datetime | None] = mapped_column( |
| DateTime(timezone=True), |
| nullable=True, |
| ) |
| trial_ends_at: Mapped[datetime | None] = mapped_column( |
| DateTime(timezone=True), |
| nullable=True, |
| ) |
| |
| period_start: Mapped[datetime | None] = mapped_column( |
| DateTime(timezone=True), |
| nullable=True, |
| ) |
| monthly_video_limit: Mapped[int] = mapped_column(Integer, default=3, nullable=False) |
| monthly_video_used: Mapped[int] = mapped_column(Integer, default=0, nullable=False) |
| monthly_generation_limit: Mapped[int] = mapped_column(Integer, default=30, nullable=False) |
| monthly_generation_used: Mapped[int] = mapped_column(Integer, default=0, nullable=False) |
| created_at: Mapped[datetime] = mapped_column( |
| DateTime(timezone=True), |
| server_default=func.now(), |
| nullable=False, |
| ) |
| updated_at: Mapped[datetime] = mapped_column( |
| DateTime(timezone=True), |
| server_default=func.now(), |
| onupdate=func.now(), |
| nullable=False, |
| ) |
|
|
| |
| |
| __table_args__ = ( |
| Index("ix_user_plans_selected_plan_status", "selected_plan", "status"), |
| Index("ix_user_plans_period_start", "period_start"), |
| ) |
|
|