89 lines
4.1 KiB
Python
89 lines
4.1 KiB
Python
from datetime import datetime
|
|
from typing import TYPE_CHECKING
|
|
|
|
from sqlalchemy import (
|
|
DateTime,
|
|
Enum,
|
|
ForeignKey,
|
|
Index,
|
|
Integer,
|
|
String,
|
|
func,
|
|
)
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.db.base import Base
|
|
from app.models.enums import OrderStatus, TicketStatus
|
|
|
|
if TYPE_CHECKING:
|
|
from app.models.catalog import Event, TicketType
|
|
|
|
|
|
class Order(Base):
|
|
__tablename__ = "orders"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="RESTRICT"), index=True)
|
|
event_id: Mapped[int] = mapped_column(ForeignKey("events.id", ondelete="RESTRICT"), index=True)
|
|
status: Mapped[OrderStatus] = mapped_column(Enum(OrderStatus), default=OrderStatus.pending, index=True)
|
|
total_paise: Mapped[int] = mapped_column(Integer)
|
|
currency: Mapped[str] = mapped_column(String(3), default="INR")
|
|
payment_reference: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
|
provider_order_id: Mapped[str | None] = mapped_column(String(64), unique=True, nullable=True, index=True)
|
|
provider_payment_id: Mapped[str | None] = mapped_column(String(64), nullable=True, index=True)
|
|
idempotency_key: Mapped[str | None] = mapped_column(String(64), unique=True, nullable=True, index=True)
|
|
expires_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True, index=True)
|
|
paid_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), 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(),
|
|
)
|
|
|
|
items: Mapped[list["OrderItem"]] = relationship(
|
|
"OrderItem",
|
|
back_populates="order",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
tickets: Mapped[list["Ticket"]] = relationship(
|
|
"Ticket",
|
|
back_populates="order",
|
|
cascade="all, delete-orphan",
|
|
)
|
|
event: Mapped["Event"] = relationship("Event")
|
|
|
|
|
|
class OrderItem(Base):
|
|
__tablename__ = "order_items"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
order_id: Mapped[int] = mapped_column(ForeignKey("orders.id", ondelete="CASCADE"), index=True)
|
|
ticket_type_id: Mapped[int] = mapped_column(ForeignKey("ticket_types.id", ondelete="RESTRICT"), index=True)
|
|
quantity: Mapped[int] = mapped_column(Integer)
|
|
unit_price_paise: Mapped[int] = mapped_column(Integer)
|
|
line_total_paise: Mapped[int] = mapped_column(Integer)
|
|
|
|
order: Mapped["Order"] = relationship("Order", back_populates="items")
|
|
ticket_type: Mapped["TicketType"] = relationship("TicketType")
|
|
tickets: Mapped[list["Ticket"]] = relationship("Ticket", back_populates="order_item")
|
|
|
|
|
|
class Ticket(Base):
|
|
__tablename__ = "tickets"
|
|
__table_args__ = (Index("ix_tickets_user_status", "user_id", "status"),)
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
|
code: Mapped[str] = mapped_column(String(32), unique=True, index=True)
|
|
order_id: Mapped[int] = mapped_column(ForeignKey("orders.id", ondelete="CASCADE"), index=True)
|
|
order_item_id: Mapped[int] = mapped_column(ForeignKey("order_items.id", ondelete="CASCADE"), index=True)
|
|
ticket_type_id: Mapped[int] = mapped_column(ForeignKey("ticket_types.id", ondelete="RESTRICT"), index=True)
|
|
event_id: Mapped[int] = mapped_column(ForeignKey("events.id", ondelete="RESTRICT"), index=True)
|
|
user_id: Mapped[int] = mapped_column(ForeignKey("users.id", ondelete="RESTRICT"), index=True)
|
|
status: Mapped[TicketStatus] = mapped_column(Enum(TicketStatus), default=TicketStatus.valid, index=True)
|
|
qr_token: Mapped[str] = mapped_column(String(64), unique=True, index=True)
|
|
used_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
|
|
|
order: Mapped["Order"] = relationship("Order", back_populates="tickets")
|
|
order_item: Mapped["OrderItem"] = relationship("OrderItem", back_populates="tickets")
|