from __future__ import annotations from datetime import datetime from typing import Optional, List from sqlalchemy import Integer, String, DateTime, ForeignKey, Numeric, func, Text from sqlalchemy.orm import Mapped, mapped_column, relationship from shared.db.base import Base class Order(Base): __tablename__ = "orders" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) user_id: Mapped[Optional[int]] = mapped_column(Integer, nullable=True) session_id: Mapped[Optional[str]] = mapped_column(String(64), index=True, nullable=True) page_config_id: Mapped[Optional[int]] = mapped_column( Integer, nullable=True, index=True, ) status: Mapped[str] = mapped_column( String(32), nullable=False, default="pending", server_default="pending", ) currency: Mapped[str] = mapped_column(String(16), nullable=False, default="GBP") total_amount: Mapped[float] = mapped_column(Numeric(12, 2), nullable=False) # free-form description for the order description: Mapped[Optional[str]] = mapped_column(Text, nullable=True, index=True) # SumUp reference string (what we send as checkout_reference) sumup_reference: Mapped[Optional[str]] = mapped_column( String(255), nullable=True, index=True, ) # SumUp integration fields sumup_checkout_id: Mapped[Optional[str]] = mapped_column( String(128), nullable=True, index=True, ) sumup_status: Mapped[Optional[str]] = mapped_column(String(32), nullable=True) sumup_hosted_url: Mapped[Optional[str]] = mapped_column(Text, nullable=True) created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now(), ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now(), onupdate=func.now(), ) items: Mapped[List["OrderItem"]] = relationship( "OrderItem", back_populates="order", cascade="all, delete-orphan", lazy="selectin", ) # page_config_id references PageConfig in db_blog (cross-domain). # Fetch via HTTP: fetch_data("blog", "page-config-by-id", params={"id": ...}) class OrderItem(Base): __tablename__ = "order_items" id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True) order_id: Mapped[int] = mapped_column( ForeignKey("orders.id", ondelete="CASCADE"), nullable=False, ) product_id: Mapped[int] = mapped_column( Integer, nullable=False, ) product_title: Mapped[Optional[str]] = mapped_column(String(512), nullable=True) product_slug: Mapped[Optional[str]] = mapped_column(String(512), nullable=True) product_image: Mapped[Optional[str]] = mapped_column(Text, nullable=True) quantity: Mapped[int] = mapped_column(Integer, nullable=False, default=1) unit_price: Mapped[float] = mapped_column(Numeric(12, 2), nullable=False) currency: Mapped[str] = mapped_column(String(16), nullable=False, default="GBP") created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), nullable=False, server_default=func.now(), ) order: Mapped["Order"] = relationship( "Order", back_populates="items", )