107 lines
4.3 KiB
Python
107 lines
4.3 KiB
Python
"""Order models."""
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
|
|
from sqlalchemy import String, Integer, Numeric, DateTime, ForeignKey, Text
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
|
|
|
from app.database import Base
|
|
|
|
|
|
class OrderStatus(str, Enum):
|
|
"""Order status enum."""
|
|
|
|
PENDING = "pending"
|
|
PAID = "paid"
|
|
PROCESSING = "processing"
|
|
PRINTING = "printing"
|
|
SHIPPED = "shipped"
|
|
DELIVERED = "delivered"
|
|
CANCELLED = "cancelled"
|
|
REFUNDED = "refunded"
|
|
|
|
|
|
class Order(Base):
|
|
"""Order model."""
|
|
|
|
__tablename__ = "orders"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
|
)
|
|
customer_id: Mapped[uuid.UUID | None] = mapped_column(
|
|
UUID(as_uuid=True), ForeignKey("customers.id"), nullable=True
|
|
)
|
|
|
|
# Payment provider info (provider-agnostic)
|
|
payment_provider: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
|
payment_id: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
payment_method: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
|
|
|
status: Mapped[str] = mapped_column(String(50), default=OrderStatus.PENDING.value)
|
|
|
|
# Shipping info
|
|
shipping_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
shipping_email: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
shipping_address_line1: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
shipping_address_line2: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
shipping_city: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
|
shipping_state: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
|
shipping_postal_code: Mapped[str | None] = mapped_column(String(20), nullable=True)
|
|
shipping_country: Mapped[str | None] = mapped_column(String(2), nullable=True)
|
|
|
|
# Financials
|
|
subtotal: Mapped[float | None] = mapped_column(Numeric(10, 2), nullable=True)
|
|
shipping_cost: Mapped[float | None] = mapped_column(Numeric(10, 2), nullable=True)
|
|
tax: Mapped[float | None] = mapped_column(Numeric(10, 2), nullable=True)
|
|
total: Mapped[float | None] = mapped_column(Numeric(10, 2), nullable=True)
|
|
currency: Mapped[str] = mapped_column(String(3), default="USD")
|
|
|
|
# Timestamps
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
|
|
)
|
|
paid_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
shipped_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
delivered_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True)
|
|
|
|
# Relationships
|
|
customer: Mapped["Customer | None"] = relationship("Customer", back_populates="orders")
|
|
items: Mapped[list["OrderItem"]] = relationship(
|
|
"OrderItem", back_populates="order", cascade="all, delete-orphan"
|
|
)
|
|
|
|
|
|
class OrderItem(Base):
|
|
"""Order item model."""
|
|
|
|
__tablename__ = "order_items"
|
|
|
|
id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4
|
|
)
|
|
order_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True), ForeignKey("orders.id", ondelete="CASCADE"), nullable=False
|
|
)
|
|
product_slug: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
product_name: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
variant: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
|
quantity: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
unit_price: Mapped[float] = mapped_column(Numeric(10, 2), nullable=False)
|
|
|
|
# POD fulfillment
|
|
pod_provider: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
|
pod_order_id: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
|
pod_status: Mapped[str | None] = mapped_column(String(50), nullable=True)
|
|
pod_tracking_number: Mapped[str | None] = mapped_column(String(100), nullable=True)
|
|
pod_tracking_url: Mapped[str | None] = mapped_column(Text, nullable=True)
|
|
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
# Relationships
|
|
order: Mapped["Order"] = relationship("Order", back_populates="items")
|