Desi-Clans/backend/app/models/orders.py
2026-10-08 02:52:58 +05:30

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")