from datetime import datetime from sqlalchemy import ( Boolean, DateTime, Enum, ForeignKey, Index, Integer, String, Text, func, ) from sqlalchemy.orm import Mapped, mapped_column, relationship from app.db.base import Base from app.models.enums import EventStatus, EventType, TicketTypeStatus class Venue(Base): __tablename__ = "venues" id: Mapped[int] = mapped_column(Integer, primary_key=True) slug: Mapped[str] = mapped_column(String(120), unique=True, index=True) name: Mapped[str] = mapped_column(String(200)) area: Mapped[str] = mapped_column(String(120)) city: Mapped[str] = mapped_column(String(80), default="Bengaluru") address: Mapped[str] = mapped_column(String(512)) map_url: Mapped[str | None] = mapped_column(String(512), nullable=True) description: Mapped[str | None] = mapped_column(Text, nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), ) events: Mapped[list["Event"]] = relationship("Event", back_populates="venue") class Event(Base): __tablename__ = "events" __table_args__ = ( Index("ix_events_status_starts_at", "status", "starts_at"), Index("ix_events_category_status", "category", "status"), ) id: Mapped[int] = mapped_column(Integer, primary_key=True) slug: Mapped[str] = mapped_column(String(200), unique=True, index=True) title: Mapped[str] = mapped_column(String(240)) category: Mapped[EventType] = mapped_column(Enum(EventType), index=True) status: Mapped[EventStatus] = mapped_column(Enum(EventStatus), default=EventStatus.draft, index=True) venue_id: Mapped[int] = mapped_column(ForeignKey("venues.id", ondelete="RESTRICT"), index=True) description: Mapped[str | None] = mapped_column(Text, nullable=True) starts_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), index=True) ends_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True) is_featured: Mapped[bool] = mapped_column(Boolean, default=False) cover_image_url: Mapped[str | None] = mapped_column(String(1024), nullable=True) cover_image_alt: Mapped[str | None] = mapped_column(String(300), nullable=True) meta_description: Mapped[str | None] = mapped_column(String(320), nullable=True) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), ) venue: Mapped["Venue"] = relationship("Venue", back_populates="events") media: Mapped[list["EventMedia"]] = relationship( "EventMedia", back_populates="event", cascade="all, delete-orphan", order_by="EventMedia.sort_order", ) ticket_types: Mapped[list["TicketType"]] = relationship( "TicketType", back_populates="event", cascade="all, delete-orphan", order_by="TicketType.sort_order", ) class EventMedia(Base): __tablename__ = "event_media" id: Mapped[int] = mapped_column(Integer, primary_key=True) event_id: Mapped[int] = mapped_column(ForeignKey("events.id", ondelete="CASCADE"), index=True) image_url: Mapped[str] = mapped_column(String(1024)) alt_text: Mapped[str | None] = mapped_column(String(300), nullable=True) sort_order: Mapped[int] = mapped_column(Integer, default=0) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) event: Mapped["Event"] = relationship("Event", back_populates="media") class TicketType(Base): __tablename__ = "ticket_types" id: Mapped[int] = mapped_column(Integer, primary_key=True) event_id: Mapped[int] = mapped_column(ForeignKey("events.id", ondelete="CASCADE"), index=True) name: Mapped[str] = mapped_column(String(120)) description: Mapped[str | None] = mapped_column(String(512), nullable=True) price_paise: Mapped[int] = mapped_column(Integer) quantity_total: Mapped[int] = mapped_column(Integer) quantity_sold: Mapped[int] = mapped_column(Integer, default=0) status: Mapped[TicketTypeStatus] = mapped_column(Enum(TicketTypeStatus), default=TicketTypeStatus.active) sort_order: Mapped[int] = mapped_column(Integer, default=0) created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), ) event: Mapped["Event"] = relationship("Event", back_populates="ticket_types")