from __future__ import annotations from datetime import datetime from decimal import Decimal from sqlalchemy import DateTime, ForeignKey, Index, Numeric, String from sqlalchemy.orm import Mapped, mapped_column from app.enums.credit_subscription import CreditSubscriptionPeriodStatus from app.models.base import Base, TimestampMixin class UserCreditSubscriptionPeriod(Base, TimestampMixin): __tablename__ = "user_credit_subscription_periods" __table_args__ = ( Index("uq_user_credit_subscription_periods_sequence", "subscription_id", "sequence", unique=True), Index("ix_user_credit_subscription_periods_due", "status", "scheduled_at", "id"), Index("ix_user_credit_subscription_periods_upgrade", "upgrade_order_id", "status"), Index("uq_user_credit_subscription_periods_balance", "issued_balance_id", unique=True), ) id: Mapped[str] = mapped_column(String(32), primary_key=True) subscription_id: Mapped[str] = mapped_column( String(32), ForeignKey("user_credit_subscriptions.id", ondelete="CASCADE"), nullable=False ) sequence: Mapped[int] = mapped_column(nullable=False) scheduled_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False) valid_from: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False) expires_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), nullable=False) grant_credits: Mapped[Decimal] = mapped_column(Numeric(20, 2), nullable=False) allocated_paid_amount: Mapped[Decimal] = mapped_column(Numeric(20, 2), nullable=False) status: Mapped[str] = mapped_column( String(32), nullable=False, default=CreditSubscriptionPeriodStatus.SCHEDULED.value, server_default=CreditSubscriptionPeriodStatus.SCHEDULED.value, ) issued_balance_id: Mapped[str | None] = mapped_column( String(32), ForeignKey("user_credit_balances.id", ondelete="SET NULL"), nullable=True ) issued_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) upgrade_order_id: Mapped[str | None] = mapped_column( String(32), ForeignKey("payment_orders.id", ondelete="SET NULL"), nullable=True ) reserved_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) cancelled_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) revoked_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)